From Side Project to Paid Product: Iterating Holdie With Claude Code
A follow-up on what's changed since the first article: payments, email, imports, observability, and what the development process actually looks like day to day.
The first article covered the infrastructure behind Holdie: where it's hosted, how the database works, what APIs it connects to. Since writing it, the product has moved on considerably. A 30-day free trial and paid subscription went live. A proper email system is running. Users can import their holdings from a spreadsheet. Error monitoring and analytics are now in place. None of it required a development agency or a technical co-founder.
Payments: Lemon Squeezy, Not Stripe
The first article flagged Stripe as the obvious path for payments. In practice, Lemon Squeezy turned out to be a better fit for a small product at this stage. The key difference is that Lemon Squeezy acts as the merchant of record, which means it handles GST and international tax compliance automatically. Stripe hands that responsibility back to you. For a solo product targeting New Zealand users, that simplification matters.
The checkout UI lives entirely on Lemon Squeezy's servers, so there was nothing to design or build there. When a user subscribes, Lemon Squeezy sends a webhook to a Supabase Edge Function, which updates the user's subscription status in the database. Holdie then checks that status on every dashboard load and either opens the app or shows a prompt to subscribe. The trial counter runs off a trial_ends_at timestamp set when the account is created.
Email: Resend and the Auth Hook
Supabase handles user authentication, but its built-in email templates are fairly limited. The solution is an Auth Hook, which is a Supabase Edge Function that intercepts every outgoing auth email (magic links, confirmations, password resets) before it's sent and reroutes it through Resend, a transactional email service. This gives full control over the email design while keeping Supabase in charge of the authentication logic. Holdie's magic link emails now arrive from hello@holdie.io with a clean layout rather than the Supabase default.
Lifecycle emails sit alongside this. A database webhook fires whenever a new user profile is created, calling a separate Edge Function that sends a welcome email via Resend. This is where future emails will live too: trial expiry reminders, snapshot nudges, monthly summaries.
The Import Feature
A significant chunk of Holdie's potential users already have their investments tracked somewhere else, usually a spreadsheet or a platform like Sharesies. The import feature handles this by accepting CSV and Excel files and parsing them into holdings automatically. For known formats (Sharesies investment holdings, generic name/type/value spreadsheets) the parsing happens entirely in the browser using a library called SheetJS. For everything else, the file is sent to a Supabase Edge Function that passes it to Claude Haiku, a lightweight AI model, which extracts whatever it can find and returns it as structured data. The result is that most files just work, and genuinely unusual ones get a reasonable attempt rather than an error.
Observability: Sentry and Plausible
For most of Holdie's development, there was no error monitoring in place. If something broke quietly in production, it was invisible. Sentry now catches unhandled JavaScript errors and promise rejections in the React app and surfaces them in a dashboard. This matters most for the subscription flow: a failed webhook or a broken access check is exactly the kind of bug that would otherwise only be noticed when a user complained.
Plausible handles analytics. It is privacy-friendly, GDPR-compatible, and adds a single script tag to the page. Page views across all routes are tracked automatically, which means the conversion funnel from landing page to dashboard is visible with no extra setup. Custom events track the key actions: magic link sent, holding added (with the type as a property), snapshot saved, checkout started, import used. That set of events maps directly to the product's core value loop and gives a clear picture of where users are dropping off.
What the Development Process Actually Looks Like
The first article described the tools. This one is a good place to be more honest about the process itself. All of the above was built through conversation with Claude Code, Anthropic's AI coding assistant. The way that works in practice is closer to directing a senior engineer than to using a code generator.
The most useful shift is thinking in product decisions rather than implementation details. When setting up Sentry, the questions that needed answering were: EU or US data residency? Error monitoring only, or session replay too? Those are product and compliance calls. Claude Code handles the implementation once the direction is set. When setting up Plausible analytics, the question was which events actually matter for understanding the product. The instrumentation followed from having a clear answer to that.
Claude Code maintains memory across sessions through a file-based system in the project directory. It knows the subscription logic, the edge function constraints, the deploy process, the brand colours, and the decisions made in previous sessions. Starting a new session doesn't mean re-explaining the project from scratch. This accumulation of context is probably the biggest practical advantage over using an AI assistant on an ad-hoc basis.
The iteration speed is genuinely fast. Sentry and Plausible, including fixing a Content Security Policy issue that blocked the Plausible script on first attempt, went from zero to deployed in about an hour. That includes installing packages, wiring up events across multiple files, updating the CSP headers, and running two production deploys. The bottleneck is rarely the code. It's having a clear enough idea of what you want to build and being able to communicate it efficiently.
What this model does not do is remove the need for product judgment. Every meaningful decision (which payment provider, what to track in analytics, how the trial should work, what the email copy should say) still requires a human with a view on what the product is for and who it's for. Claude Code is very good at executing on a clear brief and flagging when something is missing or inconsistent. It's less useful when the brief itself is vague. The quality of what gets built reflects the quality of the product thinking behind it, just as it would with any engineer.