My business · Client portal and website · Side project
Safe As Houses: a client portal and website for my digital security advisory
Safe As Houses helps people make their digital lives secure and recoverable. I built its client portal and public website alone with Claude Code. Since late September, every change has gone through the same review-and-test pipeline a software company would use.





What it is
Safe As Houses is a personal digital security and continuity advisory. In one-to-one sessions, in person or on a video call, it helps people sort out their email, their Apple or Google account, their passwords and their phone company, one thing at a time, and plan for the bad days: a lost phone, a taken-over account, a family that needs to step in. Clients make every change themselves; Safe As Houses never sees or keeps their passwords.
The client portal holds each client’s plan, how-to guides and recovery playbooks. The public website is how new clients find it.
Why I built it
The people I know have their money, legal documents and insurance in order, and almost nothing in place for their digital lives: who can get into what, and what happens if they lose a phone or worse. I wanted to offer that help properly, and I wanted to find out how far one product manager can get with AI as the engineering team.
What’s in it
- 1An Exposure Snapshot: a plain-language look at where someone’s email already appears in known data breaches.
- 2An intake questionnaire clients complete on their own time.
- 3A written assessment, scored across six areas, that Claude helps me draft and I review before the client sees it.
- 4A plan in phases, where every task links to a how-to guide and says why it matters.
- 5Print-ready recovery playbooks for situations like a lost phone or a taken-over email account.
- 6Access for trusted contacts, so the right people can act when the client can’t, without anyone holding the client’s passwords.
- 7Engagement letters signed in the portal.
How it’s built
Claude Code agents write almost all of the code. I set the direction, make the technical calls below, and approve every change on its own private preview. Since late September, each one has been a pull request that can’t merge until the required checks pass.
The stack
Two Next.js apps, the client portal and the public website, sharing one design system.
App
- Next.jsBoth apps, on the App Router
- React
- TypeScriptEvery file, in strict mode
- Tailwind CSSStyling, on design tokens both apps share
- TiptapThe rich-text editor I write the how-to guides in
Data and services
- SupabaseDatabase, sign-in and file storage
- PostgreSQLRow-level security: the database itself decides what each signed-in person can read
- ZodValidates every request to the server, field by field
- ResendSign-in and plan-update emails
- Have I Been PwnedBreach records behind the Exposure Snapshot
- VercelHosting for both apps, with a private preview for every pull request
AI
- Anthropic APIClaude helps draft each assessment, behind one layer that every AI call goes through
Quality and delivery
- VitestAbout 1,100 unit tests
- PlaywrightBrowser tests against every preview
- GitHub ActionsThree required checks on every pull request: type checks, lint and unit tests; a production build; and the data-access tests
- GitHubPull requests and a protected main branch
- Claude CodeThe agents that write the code, coordinated by one lead session
Technical decisions
- 1Data isolation in the database, not only in application code. With row-level security, keeping clients apart doesn’t depend on every server route getting its checks right. The cost is access rules that are harder to write and test, so a test suite checks them against a copy of the production schema on every pull request.
- 2One layer for every AI call, instead of each feature calling the API its own way. All seven AI features go through it: it adds timeouts and retries, rejects an answer with the wrong structure before a client could see it, and maps each task to a model. Today every task uses the same Claude model; the map is there so one task can move to a cheaper or stronger model without touching the rest.
- 3Names stay out of prompts. Client names are swapped for placeholders before a prompt is sent and restored in the answer, so the AI provider never receives them. An AI draft is never final: I review every assessment before the client sees it.
- 4No secrets in the portal. It never stores passwords, recovery codes or seed phrases, by design, so there are none in it to lose.
- 5Production database changes are applied by a person, not a pipeline. The database holds client data and a bad change is hard to undo, so every change is tested on a disposable copy first and then applied by hand, in order. It’s slower, and deliberately so.
- 6One place for client data. The public website is a separate app with no database of its own.
What I learned
Writing down the reason for each rule paid off. When something went wrong, the fix was a new rule with a date and a reason, so the same mistake didn’t come back a month later in a different session.
The AI is fastest when I’m precise about the outcome and leave the code to it: describe what a client should see and do, then check it on the preview.
Results
- Built
- March to October 2026, alone
- Commits
- 354
- Pull requests merged since late September
- 91
- Unit tests
- About 1,100
- Written plans, each with my original request
- 134
How it gets built
The pipeline I build with, and the rules behind it, are on How I build with AI.