- meta
- principles
The Boilerplate Philosophy: Boring Tech, Sharp Execution
Every architectural decision in this repo stems from one rule: make the boring choice, then execute it better than anyone expects.
Published on
The rule that governs every decision
There is exactly one architectural rule in this repository: pick the boring choice, then execute it better than anyone expects.
"Boring" does not mean old. It means well-understood — a technology whose failure modes are documented, whose community has already debugged the edge cases, and whose upgrade path will not require a rewrite in eighteen months. Next.js, Postgres, Stripe, Resend: not exciting in 2026, but still the stack a solo founder can maintain alone at 2 AM.
"Sharp execution" is the hard part. Boring tech shipped sloppily is still slow, still insecure, still unmaintainable. Every primitive in this repo — the audit chain, the idempotency layer, the tier-gate component — was built to the standard a Series A CTO would accept on a compliance call, not just to the standard that passes a demo.
Why not a framework on top of a framework?
The first instinct when building a boilerplate is to abstract. Build a useCurrentOrg() hook, a <ProtectedRoute> wrapper, a createServerAction() factory. Each abstraction is a reasonable local decision; collectively they become a second framework the user has to learn before they can ship.
This repo takes the opposite stance: read the Next.js docs, write Next.js code. Server actions are async function with 'use server'. Route handlers are export async function GET(request: Request). Nothing is wrapped unless the wrapping solves a problem that cannot be solved inline.
The one exception is database access. Drizzle is a thin enough query builder that it reads like SQL; the schema file is the single source of truth; and migrations are plain SQL you can inspect in migrations/. That is as far as the abstraction goes.
Defensibility over cleverness
Every claim on the landing page must be backed by code or a contract. That constraint shapes the feature set more than any product vision. "Tamper-evident audit chain" means a Postgres trigger that refuses deletes, not a soft deletedAt column. "GDPR data export" means a Zod-validated archive in Storage, not a commented-out TODO.
When the next wave ships, the same standard applies. If a feature cannot be defended in an audit, it does not ship as a built-in — it goes in the backlog until it can be done properly.
What this means for your fork
Clone this repo and you inherit the philosophy along with the code. The bracketed placeholders ([YOUR-COMPANY-NAME], [YOUR-NAME]) mark every spot where the boilerplate ends and your product begins. Replace them, swap the brand tokens in tailwind.config.mjs, point STRIPE_PRICE_* at your own price IDs, and you have a defensible starting point — not a marketing template, not a toy, but a foundation that will still make sense when your first auditor asks for the trail.
The blog you are reading now is part of that foundation. It is the place where the decisions get explained — not justified after the fact, but documented at the time they are made, so the next developer who inherits the codebase understands not just what was built, but why.
Share