Pulse for Shopify App Store
Taking an internal buying dashboard multi-tenant and shipping it as a public Shopify App Store app.

In build, not yet submitted. The app is registered, the install and authentication flow is in place, merchant data is isolated in its own schema, and the mandatory privacy webhooks are implemented and tested.

Current Status
Still ahead: the three reports rebuilt against Shopify’s embedded UI, Shopify-native billing, and App Store submission.
Status: In build — not yet submitted to the Shopify App Store. Everything below is design and engineering decisions, not measured outcomes.
The Constraint
Pulse solved a problem that is not unique to Avnzor — but I had built it as though it were.
The internal dashboard reads Avnzor’s Shopify store, but it also reads a MySQL warehouse database, a consignment supplier’s stock feed, in-transit purchase orders, weather data and competitor prices. That mix is exactly what makes it sharp for one merchant and impossible for any other merchant to install.
Every Shopify merchant holding inventory has the same four questions Pulse was built to answer. The work here is separating the part of the system that only needs Shopify from the part that needs Avnzor — and turning the first half into something a stranger can install in two clicks.
In build: OAuth and embedded session handling, per-merchant data isolation, the mandatory privacy webhooks, and Shopify-native billing.

The System I Introduced
I asked which of Pulse’s twenty-eight pages would still work on a store I had never seen.
The answer was smaller than I expected, and more valuable. The classification logic at the centre of Pulse — the thing the buying team actually trusts — needs nothing but Shopify. Units on hand set the severity band. Thirty days of paid orders set the order you work in. Everything else is enrichment.
That distinction is easy to lose. Velocity feels like it should promote an item to critical, but it never does — it decides which of the forty critical items gets dealt with before lunch. Keeping the two inputs doing separate jobs is why the list stays readable when it is long, and it is the piece that ports cleanly to any store.
Key Decisions
Ship a wedge, not the dashboard
Context: The internal Pulse is twenty-eight pages, and most of them read data no other merchant has — a MySQL warehouse, a consignment supplier’s feed, in-transit purchase orders, weather, competitor prices. The question that scoped the product was which of those pages would still work on a store I had never seen.
Choice: Three reports — Stock Risk, Sell-Through, Top Sellers — instead of twenty-eight pages. One clear job, a small support surface, and room to learn what merchants actually ask for before building more.
Trade-off: The features that make Pulse sharp for Avnzor are exactly the ones that cannot travel. What ships is only the part built on the Admin API every merchant already has.
Adopt Shopify’s app framework rather than porting the Next.js build
Context: I had already hand-written OAuth, token encryption and webhook verification for the internal build, and all of it worked.
Choice: Shopify’s React Router template provides those as maintained library code, plus embedded session tokens and the Billing API. They are the fiddly, security-sensitive parts, and the parts where App Store reviews fail. Throwing away working code was the cheaper decision.
Trade-off: Working code discarded, and the app now moves at the template’s pace and conventions rather than my own.
Isolate merchant data at the schema level
Context: One database serving many merchants, where an erasure request has to be provably complete rather than probably complete.
Choice: Every merchant-scoped table carries a tenant reference with a cascading delete, so an erasure request is a single statement that cannot silently miss a table.
Trade-off: Every future table inherits the obligation. The guarantee holds only as long as the discipline does.
Treat compliance as build work
Context: The three privacy webhooks are a submission requirement, and reviewers probe them with a deliberately invalid signature.
Choice: Tested code with an audit trail, not a checkbox.
Trade-off: Engineering time spent on a surface no merchant will ever see or pay for.


What I'd Do Differently
I would have drawn the portable-versus-local line on day one.
Nothing about the warehouse integration was wrong for Avnzor — it is genuinely useful there. But because it was wired straight through the same routes as the Shopify logic, separating the two later meant untangling rather than lifting. Had the enrichment sat behind a boundary from the start, the multi-tenant version would have been an afternoon's work instead of a rebuild.
The same applies to the database. Pulse's tables were built for one store, so none of them carried a tenant column. Retrofitting that is straightforward but unglamorous, and entirely avoidable.
Let's talk about your project.
ARES — Snap Inc.