All writing

I built a Shopify app in one sitting. It failed four times first.

I am not an engineer. I had never made a Shopify app. I did it in one sitting, and it broke four times before it worked.

I told you I was building a referral tool in public. A thing that watches for the moment a customer is happy, then fires the referral ask automatically, before the goodwill cools.

Today I built the first working version. Shopify order gets fulfilled, my server catches it, a referral email goes out. The whole loop, running.

I am not an engineer. I had never made a Shopify app. I did it in one sitting, and it broke four times before it worked. This is the real account, including the breaks, because the breaks are where the lesson lives.

What I set out to prove

One signal in, one email out. Nothing else.

A customer marks happy. The system notices. It asks for the referral while the buyer still feels good. No reminder to set, no salesperson remembering to follow up. The unscalable human act, run by a machine.

For the first build I picked Shopify, because the happiness signal there is clean. An order marked fulfilled is a real moment of goodwill. I chose that one event and ignored everything else.

The plan was three pieces. Shopify sends a message when an order is fulfilled. A small program on my laptop catches the message. The program sends a referral email. That is the entire loop.

The four failures, in order

One. The code could not read its own keys.

A tool like this needs secrets. An email key, a key to verify messages are really from the right place. You keep those in a separate file so you never paste them into the code itself.

I pasted my email key into the file. Started the program. It crashed. Missing API key.

The fix was a single line that tells the program to read the secrets file when it starts. Without that line, the program looks for the key, finds nothing, gives up. One line. The kind of thing that stops you dead and feels like a wall until you see it.

Two. The Shopify app builder sent me down a hole.

Shopify changed how you build apps. The new flow wanted scopes, redirect URLs, an install process, the full machinery for an app you distribute to the public. I started filling it in. Then I stopped.

I did not need a public app. I needed one event reaching my server. There was a far simpler door in the same admin, a plain webhook creator built into store notifications. Pick the event, paste the address, done. No scopes, no install flow.

The lesson costs nothing and saves hours. When the official path feels like it is asking for ten times more than your task needs, look for the smaller door. It is usually right there.

Three and four. The signature would not match.

This is the one that nearly beat me, and the one worth reading closely.

Every message from Shopify is signed, so your server can confirm it is real and not a fake. Your code recomputes that signature and checks it matches. Mine kept rejecting every message. Refusing to trust them.

Rejecting is the safe failure. The code was doing its job, turning away messages it could not verify. But it meant nothing was getting through.

I had a theory about why. I tried it. Still rejected. I tried the opposite. Still rejected. Two reasonable guesses, both wrong, no progress.

So I stopped guessing. I made the code print the actual numbers. What Shopify sent, what my code computed, and the length of my secret key.

The answer was in one line. My secret was 63 characters long. It should have been 64. One character had gone missing when I pasted it. A single missing character produces a completely different signature, so nothing ever matched.

I pasted the full key. Fired one more order. Email sent.

The lesson worth keeping

The first three failures were small traps. The fourth taught the real skill.

I wasted two attempts flipping between guesses. The moment I printed the evidence instead of guessing, the cause was obvious in seconds. The secret was one character short. Nothing clever fixed it. Looking at the actual data fixed it.

Stop guessing. Print the evidence. That is most of debugging, and you do not need to be technical to do it. You need to be willing to look at what is in front of you instead of arguing with the machine in your head.

Where this goes

The loop works. A real product is more than a loop, and I am building toward that in the open. You watched the first version get made, breaks and all.

Next time I am picking the signal apart. Order fulfilled is a decent signal, but it is not the strongest one, and there is a signal most people would reach for that is quietly the wrong choice. It looks like happiness. It is not. Reaching for it is how a lot of referral tools end up asking at the wrong moment.

That mistake, and the better signal underneath it, next.


Founding members get every build as I ship it. The code, the signals, the teardowns, the things that break. $150 for the year, locked at the founding rate while the price climbs. This is for operators who want to watch the machine get built and take the parts for their own work. If you want a finished tool to install today, wait. This is the build, live.