ZeroStarter

Quickstart

Go from one command to a running, signed-in app, and where to go next.

Two commands take you from nothing to a running, signed-in app.

Prerequisites

  • Bun, required. The repo pins bun@1.4.0 via packageManager in the root package.json. If it is missing, the CLI shows how to re-run under Bun (bunx --bun zerostarter ...) and offers to install it for you.
  • bunx, not npx. The CLI shells out to bunx to fetch the scaffold, install dependencies, provision Postgres, and migrate, streaming each step's progress.
  • Docker, optional. init uses it to provision a local Postgres automatically; without it you set POSTGRES_URL yourself.
bunx zerostarter init
bun run dev

The rest of this page is what those commands do, and the one thing to check if the database step gets skipped.

zerostarter init

bunx zerostarter init scaffolds a fresh product into the current directory, and the directory name becomes your project name. Run it in an empty folder of its own:

  • if the folder already has files, it asks for a project name and scaffolds into that new directory instead;
  • if you run it inside an existing workspace or monorepo, it stops early, because a parent lockfile would break the dependency install.

In one run it:

  • fetches the latest ZeroStarter and strips the sample content,
  • rebrands the copy to your project name, the agent skills and AGENTS.md included,
  • sets your feature flags (allowlist, API reference, blog, docs, internal docs, waitlist), from an interactive checklist or --<flag>/--no-<flag> flags,
  • installs dependencies with Bun from the shipped bun.lock, so the first install resolves from locked versions instead of a slow cold resolve (progress streams live),
  • provisions a local Postgres in Docker (via pglaunch), reusing an already-running one when you re-run init, and applies the migrations,
  • writes .env from .env.example with a freshly generated BETTER_AUTH_SECRET and AGENT_SIGNIN_ENABLED=true, which enables the local Login (agents) sign-in out of the box.

Everything else has a working default, so the scaffold runs as-is. The feature checklist is pre-checked to the defaults (all on except the allowlist and the waitlist), and any feature can be flipped later in config. The database step defaults to yes when Docker is running; pass --db to provision it without the prompt.

If Docker isn't running

init skips the database and leaves POSTGRES_URL empty. Point it at any Postgres (a hosted one like Neon works) by setting POSTGRES_URL in .env, then apply the migrations once:

bun run db:migrate

Already have a repo, or a fork?

The CLI also covers the cases init does not. Both of these require a clean tree:

  • bunx zerostarter reinit re-scaffolds an existing git repo as a fresh ZeroStarter, keeping .git and your .env* files, so your history, remote, and local secrets survive.
  • bunx zerostarter sync re-baselines an existing fork on the latest starter, updating the shared files while keeping everything your fork owns. It leaves the result as a diff for you to review and commit.

See The CLI for every flag, what each rolls back when a step fails, exactly what sync preserves, and how it treats the skills and the agent guide you have edited.

bun run dev

Turborepo starts both apps together through portless, which serves stable named .localhost URLs off one unprivileged proxy (bunx portless list shows them; in a git worktree each host is branch-prefixed so parallel checkouts never collide):

  • web (Next.js) at http://zerostarter.localhost:1355
  • api (Hono) at http://api.zerostarter.localhost:1355, with an interactive API reference at /api/docs

PORTLESS=0 bun run dev skips the proxy for fixed ports instead (web :3000, api :4000). Reach for it when:

  • OAuth. Providers reject .localhost redirect URIs, so callbacks expect the fixed ports (see Authentication).
  • *.localhost does not resolve server-side. macOS and most Linux resolve it to loopback; some containers and corporate DNS setups do not. There the web server can't reach api.<name>.localhost to render authenticated pages, and they redirect to the home page.

Sign in

A fresh scaffold has no OAuth configured yet, so the home page shows no social buttons. init already set AGENT_SIGNIN_ENABLED=true in your local .env, so the dev-only Login (agents) button is ready in the sign-in dialog: click it (or use one curl) to mint a real session locally with no OAuth round-trip, an owner the first time it creates the account. See Working with Agents for that flow.

When you're ready for real users, wire up GitHub or Google in Authentication; each button appears only once its credentials are set.

Next