Quickstart
Create a Beignet app, run it, and make one change you can watch take effect. This is the first page to follow when you are new to Beignet.
Alpha software: Beignet is experimental alpha software. The
0.0.xpackage line is for early evaluation, and APIs may change between releases.
Create an app
bun create beignet my-app
cd my-app
bun install
cp .env.example .env.localnpm create beignet@latest, pnpm create beignet, and yarn create beignet
work the same way. See the CLI reference for the setup prompts and
flags such as --api and --db.
There is one starter: a working full-stack app with a shadcn/Tailwind UI shell, Better Auth sign-in, sign-up, and settings pages, and a user-owned todos feature backed by contracts, use cases, and Drizzle/libSQL.
Generated apps include @beignet/cli as a dev dependency, so every command
after creation runs as bun beignet <command> from the app directory.
Prepare the database
bun beignet db migrateThe initial migration ships vendored in the scaffold's drizzle/ folder, so
db migrate is the only database step before the first run.
The default starter uses SQLite — nothing to install or start. If you created
the app with --db postgres or --db mysql, start the database server before
db migrate:
# Postgres 14+
docker run --rm -d -e POSTGRES_USER=beignet -e POSTGRES_PASSWORD=beignet -e POSTGRES_DB=beignet_test -p 5432:5432 postgres:17-alpine
# MySQL 8.0+
docker run --rm -d -e MYSQL_ROOT_PASSWORD=beignet -e MYSQL_DATABASE=beignet_test -p 3306:3306 mysql:8.4Start the app
bun run devOpen http://localhost:3000/sign-up and create the first account. Signing up
lands on the dashboard inside the app shell. The sidebar links to Dashboard,
Todos, and Settings, plus Devtools and the OpenAPI document while the app runs
in development.
Todos is the feature to study: create a todo, complete it with the checkbox, delete it. It exercises contracts, use cases, ports, the typed client, React Query, and React Hook Form end to end.
Make your first change
The todo title rule lives in one Zod schema that the form, the API, and the OpenAPI document all share. Tighten it and watch all three react.
Open features/todos/schemas.ts and change CreateTodoInputSchema:
export const CreateTodoInputSchema = z.object({
- title: z.string().min(1).max(120),
+ title: z.string().min(3, "Give the todo at least 3 characters.").max(120),
});With bun run dev still running:
- Open the Todos page, type
hi, and press Add. The form rejects it with your message before any request is sent, because the form helper validates with the contract's body schema in the browser. - The server enforces the same schema: any request that bypasses the form gets
a
422response with codeVALIDATION_ERRORand the same message. - Open
http://localhost:3000/api/openapiand find the todo create body schema:titlenow advertises"minLength": 3.
One schema edit changed the form, the API, and the generated docs. That is the core Beignet loop: define the shape once, let every surface consume it.
Inspect the app
bun beignet routes
bun run lint
bun beignet lint
bun beignet doctor
bun run typecheckroutes confirms which contracts are wired to route files. bun run lint
runs Biome's code lint. bun run format applies Biome formatting.
beignet lint checks that feature layers do not import runtime, UI, or
infrastructure code in the wrong direction. doctor checks for route, OpenAPI,
and resource drift. typecheck verifies that route handlers, use cases, ports,
clients, and tests still agree with the contracts.
Open these files first
| File or folder | Why it matters |
|---|---|
features/todos/contracts.ts | Endpoint shapes used by the server, the typed client, OpenAPI, and React helpers |
features/todos/schemas.ts | The shared Zod schemas you just edited |
features/todos/use-cases/ | Application behavior and validation |
server/routes.ts | Central route registry and OpenAPI contract list |
server/index.ts | Runtime composition: providers, hooks, and error mapping |
infra/app-ports.ts | Default runtime wiring for the app's dependency interfaces |
Next, read Mental model for the vocabulary these files use, then Build your first feature to generate a second feature and follow one real change end to end. App architecture has the full folder map when you want it.