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.0viapackageManagerin the rootpackage.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, notnpx. The CLI shells out tobunxto fetch the scaffold, install dependencies, provision Postgres, and migrate, streaming each step's progress.- Docker, optional.
inituses it to provision a local Postgres automatically; without it you setPOSTGRES_URLyourself.
bunx zerostarter init
bun run devThe 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.mdincluded, - 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
.envfrom.env.examplewith a freshly generatedBETTER_AUTH_SECRETandAGENT_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:migrateAlready have a repo, or a fork?
The CLI also covers the cases init does not. Both of these require a clean tree:
bunx zerostarter reinitre-scaffolds an existing git repo as a fresh ZeroStarter, keeping.gitand your.env*files, so your history, remote, and local secrets survive.bunx zerostarter syncre-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
.localhostredirect URIs, so callbacks expect the fixed ports (see Authentication). *.localhostdoes 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 reachapi.<name>.localhostto 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
- Working with Agents: sign in locally and build your first feature.
- Architecture: what you just started, and why each piece is there.
- Authentication: add OAuth, organizations, and teams.