better-auth-scaffold

v2026.09.24

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.

GitHub
安装命令
npx skhub add pproenca/better-auth-scaffold
Markdown
SKILL.md

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

ParameterRequiredDefaultDescription
presetnominimalminimal (email+password) | social (adds Google + GitHub) | advanced (social + twoFactor + magicLink)
db_provideryes—pg | mysql | sqlite (Drizzle provider)
app_nameyes—Display name (becomes 2FA issuer in authenticator apps when preset=advanced)

Optional parameters

ParameterDefaultDescription
auth_pathlib/auth.tsServer auth module path
client_pathlib/auth-client.tsClient module path
api_route_pathapp/api/auth/[...all]/route.tsCatch-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

TemplateOutput FileWhen to emit
auth.ts.templatelib/auth.tsAlways
auth-client.ts.templatelib/auth-client.tsAlways
route.ts.templateapp/api/auth/[...all]/route.tsAlways
middleware.ts.templatemiddleware.tsWhen protected_paths is non-empty
env.template.env.exampleAlways
db-schema-better-auth.ts.templatedb/schema/auth.tsAlways (stub — replace with output of better-auth generate)
db-index.ts.templatedb/index.tsWhen the project has no Drizzle client yet
email.ts.templatelib/email.tsWhen preset=advanced (and the file doesn't already exist)
sign-in-page.tsx.templateapp/sign-in/page.tsxWhen the project has no sign-in page (closes the middleware redirect loop)
permissions.ts.templatelib/permissions.tsOptional starter for org/admin plugin work

How to Use

  1. Resolve parameters. Read config.json first; for any missing required parameter (db_provider, app_name), ask the user via AskUserQuestion.

  2. 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:
      1. Find every pair of marker lines matching // PRESET[<tags>] and // /PRESET[<tags>] (or /* PRESET[...] */ / # PRESET[...] for non-JS files — same syntax, different comment style).
      2. Parse <tags> as a comma-separated list (e.g. social,advanced).
      3. If the chosen preset value is in <tags> → remove ONLY the two marker lines; keep the lines between them.
      4. If the chosen preset value is NOT in <tags> → remove the ENTIRE block including both marker lines.
      5. 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.
  3. 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).
  4. 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.

  5. 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.

发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

MIT

源路径

skills/.experimental/better-auth-scaffold

默认分支

master

最新提交

cf93c57

Tree SHA

afbb575