Requirements

  • Node.js
  • npm
  • OpenSSL for local secret generation
  • Wrangler through the project dependency
  • A Cloudflare account for remote D1 and deployment

Create A Project

Create a new app:

npm create vergekit@latest my-app

Install dependencies:

cd my-app
npm install

Local Runtime Secrets

Create local runtime secrets. The paste-free option copies the template and writes a fresh Better Auth secret:

cp .dev.vars.example .dev.vars && secret="$(openssl rand -base64 32)" && awk -v secret="$secret" 'BEGIN { done = 0 } /^BETTER_AUTH_SECRET=/ { print "BETTER_AUTH_SECRET=" secret; done = 1; next } { print } END { if (!done) print "BETTER_AUTH_SECRET=" secret }' .dev.vars > .dev.vars.tmp && mv .dev.vars.tmp .dev.vars

Or copy the file and fill the secret manually:

cp .dev.vars.example .dev.vars

Generate a Better Auth secret:

openssl rand -base64 32

Add it to .dev.vars:

BETTER_AUTH_SECRET=your-generated-secret

Local callback URLs usually stay in .dev.vars:

BETTER_AUTH_URL=http://localhost:4321

Committed, non-secret app defaults live in wrangler.jsonc under vars. Use .dev.vars only for local secrets or local-only overrides.

Database

Apply local D1 migrations:

npm run db:migrate:local

Regenerate migrations after schema changes:

npm run db:generate

Optionally create a verified local user with the admin role after migrations:

npm run init:admin

This writes directly to D1 with Wrangler and does not require npm run dev.

Local dev uses Wrangler/Miniflare-backed D1 state through the Astro Cloudflare adapter; no separate Miniflare config is required after npm install.

See D1 Setup for production database setup, Drizzle Studio notes, and alternate local or Cloudflare-hosted development database options.

Auth Routes

All routes are public until they opt into auth. Add protected exact paths or URL prefixes in src/config/auth.ts, or check Astro.locals.isAuthenticated inside a specific page or route handler.

See Route Authentication for middleware-protected and route-local examples.

Better Auth plugins are configured in src/auth/server.ts and src/auth/client.ts. The admin plugin is already installed and configured for the app role model. See Route Authentication for the plugin files that usually need to change when adding or modifying Better Auth plugins.

Email

The default local email provider is console.

Use it for local setup when you only need links printed to the terminal:

EMAIL_PROVIDER=console

For full auth behavior with delivered verification and reset emails, configure a real provider before testing auth:

EMAIL_PROVIDER=resend
EMAIL_FROM="VK <noreply@example.com>"
RESEND_API_KEY=your-api-key

Mailgun uses:

EMAIL_PROVIDER=mailgun
EMAIL_FROM="VK <noreply@example.com>"
MAILGUN_API_KEY=your-api-key
MAILGUN_DOMAIN=mg.example.com

Cloudflare Email uses the EMAIL binding from wrangler.jsonc.

See Email Sending for direct send examples, provider requirements, auth-email helpers, and testing notes.

Configuration

Editable app defaults and auth policy live in src/config. Runtime Worker values live in wrangler.jsonc vars. Local secrets live in .dev.vars, and deployed secrets live in Wrangler secrets.

See Configuration Guide for the full split.

Run

Start the dev server:

npm run dev

Run the full local check:

npm run verify

npm run verify runs type checks, linting, tests, and the production build.