| name | better-auth-scaffold |
| description | Scaffolds a Better Auth setup in a Next.js (App Router) + Drizzle project — lib/auth.ts, lib/auth-client.ts, the /api/auth/[...all] route handler, middleware.ts, .env.example, and a permissions module. Produces convention-enforced templates for three plugin presets (minimal, social, advanced with twoFactor+magicLink). Trigger even when the user doesn't explicitly say "scaffold" — phrases like "set up Better Auth", "wire up auth", "initialize auth in this project", or "add auth to Next.js" should pull this in. Pairs with the `better-auth` skill, which covers the rules these templates encode. |
Better Auth Scaffold (Next.js + Drizzle)
Parameterized templates for bootstrapping a Better Auth setup in a Next.js App Router project using the Drizzle adapter. Each template enforces the conventions documented in references/conventions.md — file layout, plugin ordering, env handling, runtime selection.
When to Apply
Reference these templates when:
- Starting a new Next.js project that needs authentication
- Adding Better Auth to an existing Next.js + Drizzle codebase
- Refactoring a partial Better Auth setup that's missing the catch-all route, middleware, or
nextCookies() ordering
- Generating a per-feature variant (minimal, social, advanced) on top of an existing project
Setup
Required parameters
| Parameter | Required | Default | Description |
|---|
preset | no | minimal | minimal (email+password) | social (adds Google + GitHub) | advanced (social + twoFactor + magicLink) |
db_provider | yes | — | pg | mysql | sqlite (Drizzle provider) |
app_name | yes | — | Display name (becomes 2FA issuer in authenticator apps when preset=advanced) |
Optional parameters
| Parameter | Default | Description |
|---|
auth_path | lib/auth.ts | Server auth module path |
client_path | lib/auth-client.ts | Client module path |
api_route_path | app/api/auth/[...all]/route.ts | Catch-all route handler path |
protected_paths | ["/dashboard"] | Routes the middleware guards |
If config.json already exists with values, the skill uses those; otherwise it asks the user.
Available Templates
How to Use
-
Resolve parameters. Read config.json first; for any missing required parameter (db_provider, app_name), ask the user via AskUserQuestion.
-
Render each template. For each template file:
- Read the template.
- Substitute
{{placeholder}} values ({{app_name}}, {{db_provider}}, etc.) with the resolved parameter values.
- Apply
PRESET[...] conditional blocks using these rules:
- Find every pair of marker lines matching
// PRESET[<tags>] and // /PRESET[<tags>] (or /* PRESET[...] */ / # PRESET[...] for non-JS files — same syntax, different comment style).
- Parse
<tags> as a comma-separated list (e.g. social,advanced).
- If the chosen preset value is in
<tags> → remove ONLY the two marker lines; keep the lines between them.
- If the chosen preset value is NOT in
<tags> → remove the ENTIRE block including both marker lines.
- Markers may be nested (e.g.
PRESET[advanced] inside PRESET[minimal,social,advanced]); process from inside out.
- For Mustache-style iteration in
middleware.ts.template (// {{#protected_paths}} ... // {{/protected_paths}}), repeat the lines between the markers once per item in the list, substituting {{path}} with each value.
-
Write output files. Before writing, check if the target file already exists:
- If it doesn't exist → write it.
- If it exists and is identical → no-op.
- If it exists and differs → show a diff and ask the user (overwrite / merge / skip).
-
Run the CLI sequence. After all files are written:
npx @better-auth/cli@latest generate
npx drizzle-kit generate
npx drizzle-kit migrate
These commands replace the placeholder db/schema/auth.ts with the real schema and apply migrations.
-
Print next steps. Tell the user to:
- Fill in
.env.local (copy from .env.example)
- Generate a secret:
openssl rand -base64 32
- Register OAuth redirect URIs with each provider console (for
social/advanced presets)
- Implement
lib/email.ts to wire transactional email (for advanced preset)
Conventions
Read references/conventions.md for the rationale behind every convention these templates encode. Highlights:
lib/auth.ts is server-only (import "server-only")
nextCookies() is ALWAYS the last plugin in the array
- Middleware does a cookie-presence check only; real validation in pages
- All secrets via
process.env.*, never inline
- Sliding-window sessions with
cookieCache enabled
Related Skills
better-auth — Library/API Reference with 42 rules covering setup, sessions, security, plugins, and migration. The templates here are one canonical realization of those rules; read the rule for the underlying reasoning when you need to deviate.
Gotchas
See gotchas.md — initialized empty, populated as we discover them.