Quickstart
From nothing to a deployed CRUD app: a scaffolded project, a resource with a working REST API and admin screens, and a live URL. No file in this loop is hand-written.
Pick a stack below and the whole page follows it — including the deploy section at the end.
Two other ways through this material: the command builder turns your choices — stack, storage, theme, sign-in — into the one command to copy; and the step-by-step tutorials build a contact app with more explanation than this page stops for, on Next.js or on Cloudflare.
1. Scaffold and run it
Section titled “1. Scaffold and run it”Postgres, S3 and Redis are real services on this stack, so they have to come from somewhere. That is the only decision here.
Three accounts, all on free tiers. Create them first:
- Postgres — a project on Neon. Copy the pooled connection string.
- Files — an R2 bucket and an API
token. Only needed for uploads; skip it until you add a
filefield. - Redis — optional. Rate limits fall back to in-memory without it, which is fine on one machine. For the real thing, an Upstash database.
pnpm create flare-framework myappcd myapp
# paste DATABASE_URL into .env, plus the R2_* keys if you want uploadsnpx flare migrate # create the tablesnpx flare db:seed # an account to sign in withnpx flare dev # http://localhost:3000Then your first resource, from a second terminal in the app:
npx flare gen resource Contact --fields 'name:string, email:email!, status:enum(lead,customer)'npx flare migrate # create its tablenpx flare seed:resource Contact 1000flare create already wrote the .env with a fresh BETTER_AUTH_SECRET, so
DATABASE_URL is the only line you have to fill in before flare migrate.
Docker Desktop running, and nothing else to arrange — Postgres, MinIO and
Redis all come up from the docker-compose.yml in your new app.
pnpm create flare-framework myappcd myappdocker compose up -d # Postgres, MinIO and Redisnpx flare migrate # create the tablesnpx flare db:seed # an account to sign in withnpx flare dev # http://localhost:3000Then your first resource, from a second terminal in the app:
npx flare gen resource Contact --fields 'name:string, email:email!, status:enum(lead,customer)'npx flare migrate # create its tablenpx flare seed:resource Contact 1000That is the whole setup. flare create wrote a .env holding a fresh
BETTER_AUTH_SECRET and the addresses these three listen on, so there is
nothing to edit first.
| Service | What it stands in for | Where |
|---|---|---|
postgres |
Neon, or any Postgres | 127.0.0.1:5432 |
minio |
Cloudflare R2 — it speaks S3, so the same code works | 127.0.0.1:9000, console on :9001 |
redis + redis-http |
Upstash — the proxy speaks Upstash’s REST protocol | 127.0.0.1:8079 |
docker compose down stops them; add -v to throw the data away too.
Nothing to install, and no accounts. Wrangler simulates the whole platform on your machine: D1 is a local SQLite file, R2 is a local directory, KV and Durable Objects run in the same process. There is no database to provision and no bucket to create.
pnpm create flare-framework myapp --stack cloudflarecd myappnpx flare dev # http://localhost:3000Then your first resource, from a second terminal in the app:
npx flare gen resource Contact --fields 'name:string, email:email!, status:enum(lead,customer)'npx flare migrate # apply its migrationnpx flare seed:resource Contact 1000You now have this running on http://localhost:3000:
| Where | What |
|---|---|
/ |
the app |
/dashboard |
the admin, with a Contacts screen that sorts, filters, pages and exports, and a Users screen from day one |
/api/contacts |
the REST API — GET, POST, and GET/PATCH/PUT/DELETE on /api/contacts/[id] |
/api/openapi.json |
an OpenAPI 3.1 document, generated from the same descriptor |
Sign up at /dashboard. The first account to sign up becomes the admin, so
the Contacts screen is there immediately — a new resource is admin-only until
you widen its policy.
2. What those three commands did
Section titled “2. What those three commands did”flare create scaffolded a working app before any resource existed:
sign-in and sign-up screens, a session, a database, an admin shell, and the
bindings. Add --auth-providers google,github to scaffold OAuth buttons too;
they only render once you set the matching client ID and secret.
flare gen resource read one
resource descriptor and emitted everything
it implies — about nineteen files, all into your repository:
- the schema and a migration — Prisma and Postgres, or Drizzle and SQLite
- Zod validators, strict, so there is no mass assignment
- the REST API, with auth and the policy already on it
- a typed fetch client (
resources/contact.client.ts) - list, create, edit and detail screens, with loading skeletons shaped like each one
- an admin-only policy beside the descriptor
See what gen resource emits for the full list,
and the field grammar for every type you can put
in --fields.
flare migrate applied that migration. The SQL is a file in your repo and
reads like one you wrote.
3. Deploy
Section titled “3. Deploy”Vercel owns the build and the environment, so flare deploy is the Vercel CLI
and migrations stay a separate, deliberate step:
# once: point DATABASE_URL at the production database and migrate itDATABASE_URL="<your production connection string>" npx flare migrate
npx flare deploySet the same environment variables in the Vercel project — DATABASE_URL,
BETTER_AUTH_SECRET, BETTER_AUTH_URL, and the R2_* keys if you use
uploads. Vercel builds do not run migrations, which is why the first command
is there: a deploy onto an empty database is a 500 on your first sign-up.
The Vercel guide covers preview databases and
the shadow-database error prisma migrate dev gives on serverless Postgres.
One command, and it does the whole sequence:
npx flare deploy- Applies remote D1 migrations before the new code goes live. A failed migration aborts the deploy; a first deploy lets Wrangler provision the database, then migrates it.
- Builds and deploys the Worker.
- Generates and uploads
BETTER_AUTH_SECRETif production hasn’t got one — never reusing your local dev secret — and lists any optional secrets you have not set, such as OAuth credentials orRESEND_API_KEY.
You need wrangler login once, the first time you deploy anything. Nothing to
click on a dashboard.
4. Roles, when you need them
Section titled “4. Roles, when you need them”The first account is already an admin. To grant a second person a role:
npx flare user:role them@example.com adminIt writes to whichever database DATABASE_URL points at, so set it to
production when you mean production.
npx flare user:role them@example.com admin --remoteWithout --remote it writes to the local D1 file.
Every generated resource arrives admin-only. Widen one with
flare gen policy Contact --roles admin,staff, or open it to everybody with
--roles '*'. See roles and policies.
What you just got
Section titled “What you just got”- email/password auth end to end, with sessions
- a
Contactresource with a real REST API, validation and an OpenAPI document - an admin dashboard that sorts, filters, pages and exports
- a cache invalidated automatically on every write
- a live URL
No file in this loop was hand-written, and none of it is hidden: the engine
was copied into your app, not imported from a package
you cannot read. Edit the descriptor and re-run gen resource whenever you
like — the codegen overwrite contract says
exactly what survives a re-run, and flare diff shows what you have changed.
- The Next.js tutorial — a shop, end to end
- Relationships —
belongsTo,hasMany, and the pickers they generate - File uploads — the
filefield, signed URLs and size caps - Building with AI — the agent skill, so a coding agent knows all of this