Case study · Web · Education
ADUAtlas
A paid course that takes a homeowner from "could I build an accessory dwelling unit?" to a builder-ready packet. Designed, built, and launched end to end, with a business partner on the content side.

The problem
Homeowners interested in an ADU face a wall of jurisdiction-specific rules and a market of builders who only want qualified leads. The product thesis is that the homeowner course is not the end product. It is the qualification engine: someone who finishes the course and produces a feasibility packet is the lead a builder will pay for. The site had to teach well enough to be worth paying for, and structure its output so a builder could act on it.
My role
Everything technical and most of the product design: information architecture, the course engine, the worksheet tools, billing, email, deployment, and the admin console. Course content came from my partner's own module scripts; I set one rule and held it: no invented ADU facts, and every jurisdiction-specific number is framed as "varies by municipality."
What I built
- Course engine. Nine modules, sixty-nine chapters, and ten quizzes driven from a single content store, with progress tracked per chapter so the structure can change without losing anyone's place.
- Feasibility packet. Six worksheets transcribed from a spreadsheet workbook into interactive tools: pre-site estimate with computed totals, a verification checklist, a buildable-envelope viewer, and a readiness score that rolls it all up.
- Billing and email. Stripe checkout and webhooks through Vercel serverless functions, transactional email through Resend, entitlements stored in Supabase.
- Admin console. Enrollment, progress, and content review for the two of us running it.
Architecture
ADUAtlas architecture: Vite React front end on Vercel, serverless functions for Stripe and email, Supabase for auth and data.
Difficult problems
Restructuring a live course. Midway, module eight was folded into the final module and the packet became module eight. Progress is keyed by chapter id, so the reorganization shipped without resetting anyone.
Handling provider cold starts. A hosted-database behavior presented to users as an authentication failure that looked like an app bug. Diagnosed the real cause, built an operational recovery around it, and wrote it into the runbook. The lesson: know which vendor behaviors look like outages before users tell you.
Content discipline under partner pressure. The temptation was to fill thin modules with plausible ADU facts. Instead, thin modules were written from the outline and flagged for the author's full scripts, and every number stayed conditional on the reader's city.
Decisions and tradeoffs
- Self-serve first, concierge later. A done-for-you tier was proposed early. Without traffic it would have been a consulting business wearing a product's clothes.
- Static content store over a CMS. Two authors, one repository, fast iteration. Revisit when there are more authors than engineers.
- Serverless over a long-running API. Billing and email are the only server-side needs; functions mean nothing sits idle waiting for the next sale.
