Work you cancheck.
I build Shopify stores and the CRM automation behind them, in GoHighLevel, Salesforce, and n8n. Every change ships with a receipt: what changed and what it did.
Taking new projects · replies within 24 hours
The ledger
Changes that went live on clients’ stores and CRMs, with the before and after I could check. Rows with a client name link to the write-up.
| Client | Change | Before | After | Status |
|---|---|---|---|---|
| Sydney milliner | Cart pop-up to checkout | 4 clicks to pay | 2 clicks to pay | done |
| Sydney milliner | Search that narrows | a broad search returned almost the whole catalogue | category shortcuts above results | done |
| Sydney milliner | Collection swatches | one card per colour | one card per style | in review |
| Training provider | Evidence chase rebuilt | 26 students stranded | stops when the file is complete | done |
| Training provider | Lead assignment | new leads with no owner | round robin on arrival | done |
| Displaysense | Quote requests | “email us for pricing” | draft-order quote from the store | done |
The code behind the result
Most portfolios stop at a screenshot. Here’s the part that does the work, with notes on why it’s built that way.
{%- comment -%} One card per style, with swatches {%- endcomment -%}
{%- assign style = product.metafields.custom.style.value -%}
<div class="style-card" data-style="{{ style.handle }}">
{%- for colour in style.colours.value -%}
<a class="swatch" href="{{ colour.product.value.url }}"
style="--swatch: {{ colour.hex }}"
aria-label="{{ colour.name }}"></a>
{%- endfor -%}
</div>
// What is still missing from this student’s file?
const required = $json.course.requiredDocuments;
const received = $json.contact.documents;
const missing = required.filter((d) => !received.includes(d));
return [{
json: { missing, complete: missing.length === 0 },
}];
trigger RenewalTrigger on Contract (after update) {
RenewalHandler.queueReminders(Trigger.new, Trigger.oldMap);
}
public with sharing class RenewalHandler {
public static void queueReminders(
List<Contract> rows, Map<Id, Contract> old) {
List<Task> tasks = new List<Task>();
for (Contract c : rows) {
if (c.EndDate != old.get(c.Id).EndDate) {
tasks.add(new Task(WhatId = c.Id, Subject = 'Renewal due'));
}
}
insert tasks;
}
}
Fast is a claim. Here’s the reading.
These numbers come from your own browser as this page loaded. A developer’s site is a sample of their work, so this one shows its receipt too.
Text on screen. Budget: 1.8s.
Everything this page needed, compressed.
Files the browser fetched.
Script shipped to your browser.
One of four states. Never “almost done.”
Every task is built on a copy, checked, and handed back with a clear status, so you always know where your work stands.
Before and after, the diff, and a preview link.
What shipped, what didn’t, and what’s needed to finish.
The reason, plus the closest workable alternative.
One clear question, so nothing stalls silently.
Also buildingProvey: the same four endings, as a product.An AI agent for Shopify merchants. Drop a card on a board in the Shopify admin, and the work comes back with screenshots, the diff, and a preview. 98 of 100 test cards finished. Launching soon.Read the case study →What it costs, up front
Starting prices for each service, plus what typical jobs come to. A fixed quote always follows the audit or a scoping call.
Rate card
Three business days, a ranked fix list. Credited if you build.
Quote flows, product finders, sections, speed.
GoHighLevel or Salesforce, with n8n.
Upkeep, changes, and fixes every month.
Draft Orders API, a trade-buyer form, and admin notifications. Three to five days.
The audit, then duplicate fields merged, lead routing fixed, and follow-ups rebuilt.
Declarative where it can be, Apex where volume or logic needs it, with tests.
Thirty seconds on how I work. The transcript is on the About page.
Just me. No hand-offs.
You talk to the person writing the code, from the first call to the last check.