Some of what I built on Gimmie.
These are some of the things I am proud of here. Not all of it, just the parts that matter. I am the only engineer on the consumer side, so I take features from idea to launch, then live with them in production.
A lot of the real work is the small stuff that never shows up in a demo. Forward compatibility, so a change I ship today does not break an older app version still out in the wild. Idempotency, so a webhook that fires twice does not count twice. Handling the case where two things happen at the exact same moment. I care about those, and this job gave me the room to do them right.
Gift search
The hardest feature is search. You give Gimmie a loose idea, like a gift for my mom who loves gardening, and it has to come back with real products you can actually buy.
A Claude planner reads the request and what we know about the person, then writes a search plan. We do not just throw your words at a store. We shape the search differently per store, because each store has its own way that people search on it.
Then we fan out to several stores at once and pull everything back into one shape.
We remove duplicates across stores, and we rank the results so no single store takes over the page. We cache so a second visit is fast, and there is a regenerate option that gives you fresh ideas without repeating what it already showed you.
Auth inside an iframe
Gimmie also ships a widget that merchants drop into their own Shopify store. That created a fun auth problem.
The widget runs inside the merchant site, in an iframe. Login with Google or Apple will not run in an iframe, the providers block it. So when you click a provider, we open a popup instead. The popup finishes login on our own domain, then hands the session back to the widget.
The catch is that the widget and the popup are on different domains. My first idea was BroadcastChannel, but it only talks same origin. So I used window.opener.postMessage, which works across origins. The popup posts the session back, the widget listens, and I check the message type so the widget only trusts our own messages. Auth and the widget data also live in two separate Supabase projects, so the popup finishes auth on one and the widget sets the session on the other.
Billing for the SaaS
The widget is a paid product, so I built the billing too. There are a few plans, and each includes a set number of chats per month. Past that, we charge a usage based commission, with a hard cap so a merchant is never surprised by the bill. All of it comes from one config, so the price, the limits, and the commission never drift apart.
Two shoppers can chat at the same moment, so I count each chat with one atomic database step. Two at once cannot double count, or lose a count.
There are also referral credits, where a merchant earns free months and the commission still keeps working underneath.
Referrals, invites, notifications
This is how Gimmie grows, so I kept it as its own thing. Every user becomes their own referrer. When you invite someone and they join, we connect the two of you right away and let you know.
The attribution changed over time, and that part I like. We started on Branch for mobile, because a link has to survive an app install and still know who sent it. Later we moved to Tapfiliate. Tapfiliate is built around the web, so to make it work for app installs I put a small web page in the middle. A shared link now lands on that page first. The page registers the click with Tapfiliate, then deep links you into the app. So a mobile invite still gets proper credit, even though the tracking lives on the web.
Notifications run on a fan out on write model. When something happens, I write one notification per person right then, instead of working it out later when they open the app. The in app bell updates live, and mobile gets a push. Follows go through a single database trigger, so it fires the same way whether you followed someone yourself or got auto followed from an invite. And a new notification type needs no database change. An older app that does not know that type still shows a plain card instead of breaking. That last part is the forward compatibility I mentioned up top.