← All work

Next template

A production starter for small-business websites, where architecture, privacy and security rules are enforced by tooling, not by memory.

Role
Solo: architecture, code, CI/CD, infrastructure
Period
Sep 2026 – Present
Team
Just me
Stack
Next.js 16, React 19, TypeScript, Drizzle, Neon Postgres, Tailwind 4, Playwright, Vercel

The story

Context & problem

Small local businesses need simple websites, and simple websites are where the hard parts get skipped. Cookie consent, a real privacy policy, account deletion, accessible forms, bot protection and structured data rarely fit a small budget, so they are left out or copied in half-working.

Repeating that work per client is slow and drifts: each site ends up a little different and a little wrong. I wanted one base where the right choice is the default and the wrong one fails the build.

What I did

  • Designed the folder and dependency rules and encoded them in lint; every rule in the docs says what catches it.
  • Built the pipeline: CI with a throwaway Postgres branch per run, deploys from CI, a smoke suite against production.
  • Ran compliance as engineering: GDPR, WCAG 2.2 AA with axe in the end-to-end tests, technical and local SEO.
  • Turned a security audit into 14 decisions and shipped them in six steps, from a static CSP to split secrets.

Decisions & trade-offs

The architecture is executable, not a wiki page. Only the data access layer may open a database connection; a page that imports the client fails lint, and server code in a browser bundle fails the build. The cost is friction when adding folders. The gain is a rule that does not depend on who reviews.

A real database per CI run, not mocks. Each run creates its own Postgres branch from preview, never from production, runs the integration and end-to-end tests against it and always deletes it. Runs are slower; the tests run the same SQL as production.

Bot protection that does not break the business. The platform's managed bot protection blocked WhatsApp link previews and our uptime monitor. I left it off and put a bot check on the four routes that send mail or check a password, behind a rate limit.

Outcome

  • Around 75 pull requests in six weeks, each gated by the full check and a CI run on its own database.
  • 40 unit and integration test files, axe on every end-to-end run, and a production smoke suite that passes.
  • A new client site starts with privacy, terms, an accessibility statement and SEO already in place.

Architecture