ZeroStarter

Architecture

The stack, and why each piece is here: one typed monorepo from Postgres to the DOM.

ZeroStarter is one type-safe monorepo. A single type describes a row in Postgres, the API that returns it, and the component that renders it, so a change in the database surfaces as a compile error in the UI, not a bug in production.

Everything below is wired and working together, not just listed in package.json.

The shape

Two deployable apps share four packages:

Architecture graph

A request flows in a straight line, and the types flow back:

Browser → Next.js (web) → typed RPC client → Hono (api) → Drizzle → Postgres
  • web/next renders the UI and calls the API through a client that infers its types from the backend.
  • api/hono owns the routes, validates input with Zod, and talks to the database.
  • packages/* hold the pieces both apps share: the Drizzle schema, the auth instance, validated env, and the brand config.

Because it is one repository, there is one place to look, one version of every dependency (the Bun catalog), and one graph an agent or a new teammate can hold in their head.

Why a typed monorepo

The point is not "we use TypeScript." It is that the same type crosses every boundary:

  • Rename a column in the Drizzle schema and the route that selects it stops compiling.
  • Change a route's response and the frontend call to it stops compiling.
  • There is no code generation and no schema to keep in sync: the client reads the backend's exported AppType directly.

You feel this most when you refactor: the compiler walks you from the database to the button, and nothing ships half-changed.

The stack, and why each piece is here

Runtime & build

  • Bun: runtime and package manager, one tool instead of node + npm + a bundler.
  • Turborepo: caches and orders tasks across the workspaces.

Frontend (web/next)

Backend (api/hono)

  • Hono with Hono RPC for the end-to-end types, plus OpenAPI and an interactive Scalar reference at /api/docs.
  • Rate limiting via hono-rate-limiter, keyed per user, API key, or IP.

Data & auth

  • PostgreSQL with Drizzle ORM on Bun's SQL driver, and migrations.
  • Better Auth: GitHub and Google OAuth, organizations and teams, and a role ladder that gates /console.

Everything else, wired

  • PostHog analytics (optional), Fumadocs docs with search and generated llms.txt, dynamic OG images, and SEO by default.

Tooling

  • Oxc: one Rust toolchain (oxlint + oxfmt) in place of ESLint and Prettier. Plus tsdown for backend bundling, and Lefthook + Commitlint git hooks.

What's a shell, not a feature

The auth, orgs, roles, API, database, and deploy paths are real and working. The dashboard and console pages are intentionally near-empty, auth-gated shells: a starting point for your product, not a pre-built app. The one built-out console surface is the users data table, there as the pattern to copy. Build on them.

Next