Scaffold a new fullstack back-office app
This skill bootstraps a brand-new project on the pure Next.js (App Router) fullstack stack — no tRPC, no separate API service, no SPA shell. It is the entry point for the nextjs-fullstack-starter plugin and is invoked either explicitly via /nfs-scaffold-app or when the user expresses intent to start a new back-office system on plain Next.js.
When to use this skill
Use this skill when the user is starting a brand-new project in one of these shapes:
- Internal admin dashboard / management system
- Back-office tool for staff
- Line-of-business app with CRUD over rich domain models
- Lightweight ERP / operational tool
- Solo or small-team SaaS where the main app is auth-walled
- Any "one Next.js app does everything" project
Do NOT use this skill for:
- Adding a feature to an existing project (those have their own skills —
nfs-add-auth, nfs-add-cache, nfs-add-mcp).
- Projects where the user wants tRPC + SPA mode — use the sibling plugin
nextjs-trpc-prisma-starter instead.
- Public-facing marketing sites or content sites where the patterns don't apply.
- Mobile-first products that need a typed HTTP API surface — Server Actions are web-only.
Why an interactive flow
The stack is opinionated but the project has variables (database, auth provider, whether to wire cache from day one, MCP, deploy target). Asking up front means the generated project is complete and consistent rather than half-configured. The user can always add things later via the nfs-add-* skills.
Use the AskUserQuestion tool for each step so the user gets a clean UI with options. Ask one question per call, not all at once — they shape later questions (e.g. answering "PostgreSQL" determines which Prisma adapter to install).
Conversation flow
Walk the user through these questions in this order. Stop and confirm before any file write.
1. Project name
Open-ended. Validate: lowercase, hyphens-only, no spaces, valid as both a folder name and an npm package name.
2. Project location
Options:
- New directory under current working directory (e.g.
./<project-name>/)
- Use current working directory (must be empty — check first with
ls -A)
- Custom absolute path
If "current directory" is chosen, run ls -A and abort if anything other than .git/ is present. Don't overwrite the user's stuff.
3. Database
Options:
- PostgreSQL (recommended) — production default. Uses
@prisma/adapter-pg driver.
- SQLite — for prototyping / very small deployments. No driver adapter needed.
- MySQL — if the team has existing MySQL infrastructure.
Skip MongoDB — Prisma supports it but the patterns in architecture-patterns assume relational. Tell the user that if they ask.
4. Auth
Options:
- Better Auth (recommended) — modern, RBAC built-in, MCP plugin available, credentials + magic-link + OAuth providers.
- Skip for now — generate without auth wiring; user can run
/nfs-add-auth later.
Don't offer NextAuth here — Better Auth is the locked default for this stack because it integrates cleanly with the MCP plugin and has a simpler RBAC story. If the user pushes back, talk it through, but don't generate a NextAuth scaffold.
5. Cache
Options:
- Next.js default cache (recommended for start) — built-in
cacheTag + cacheLife + updateTag. In-process. Fine until measurably not.
- Add Redis on top — wire
ioredis + a Next.js cache handler from day one. Useful if multi-process / multi-deploy cache coherence matters.
6. MCP entry point
Options:
- Yes (recommended) — wires
/api/mcp/route.ts with Better Auth's mcp plugin acting as OAuth provider. Adds one example tool. Requires Better Auth (from step 4) — if user skipped auth, warn and offer to enable both.
- Skip — easy to add later via
/nfs-add-mcp.
7. Deployment target
Options:
- Self-hosted Docker (e.g. on EC2) — adds
Dockerfile, docker-compose.yml, next.config.ts with output: 'standalone'.
- Vercel — adds
vercel.ts config, no Dockerfile, adjusts a couple of patterns (e.g. cron via Vercel Crons instead of in-process node-cron).
- Both / undecided — adds the Docker bits but doesn't strip Vercel compat.
8. Email / templates (optional)
Options:
- Skip
- Resend + Handlebars — wires
src/server/integrations/resend/, outbox pattern, retry cron.
9. PDF generation (optional)
Options:
- Skip
- Gotenberg — adds
src/server/integrations/gotenberg/ + docker-compose.yml service.
10. Confirm
Show a summary of all choices and the file/folder list that will be generated. User confirms or backs up.
Generated structure
Files generated are derived from the answers plus the templates in assets/. The canonical layout is documented in references/folder-structure.md — read it before writing.
Top level:
<project-name>/
├── src/
│ ├── app/
│ │ ├── (auth)/login/page.tsx
│ │ ├── (dashboard)/
│ │ │ ├── layout.tsx # sidebar + requireSession()
│ │ │ ├── page.tsx # placeholder home
│ │ │ └── _example/ # sample CRUD page (list + new + [id])
│ │ ├── (mcp)/mcp/route.ts # if MCP=yes
│ │ ├── api/
│ │ │ ├── auth/[...all]/route.ts # if Better Auth
│ │ │ ├── health/route.ts
│ │ │ └── webhooks/ # placeholder folder
│ │ ├── layout.tsx
│ │ └── globals.css
│ ├── server/
│ │ ├── db/client.ts
│ │ ├── auth/
│ │ │ ├── index.ts
│ │ │ ├── session.ts # requireSession()
│ │ │ └── permissions.ts # requirePermission()
│ │ ├── modules/
│ │ │ └── _example/ # sample service + schema
│ │ │ ├── _example.service.ts
│ │ │ └── _example.schema.ts
│ │ ├── actions/
│ │ │ └── _example.actions.ts # sample Server Action
│ │ ├── jobs/ # cron registration
│ │ │ └── index.ts
│ │ ├── lib/
│ │ │ ├── logger.ts
│ │ │ ├── errors.ts
│ │ │ └── cache.ts # if cache=Redis
│ │ ├── mcp/ # if MCP=yes
│ │ │ ├── registry.ts
│ │ │ └── tools/_example.ts
│ │ └── integrations/ # placeholder folder
│ ├── components/ui/ # shadcn primitives (added as needed)
│ ├── lib/utils.ts
│ ├── hooks/
│ └── env.ts # @t3-oss/env-nextjs
├── prisma/
│ ├── schema.prisma
│ ├── migrations/
│ └── seed.ts
├── tests/
│ └── e2e/ # Playwright placeholder
├── public/
├── docs/
│ ├── handoff.md # session-handoff doc (start-here for Claude)
│ └── architecture.md # link to plugin's docs/
├── instrumentation.ts # boots cron in production
├── .env.example
├── .gitignore
├── CLAUDE.md # generated, reflects choices
├── Dockerfile # if deploy=docker
├── docker-compose.yml # postgres + (gotenberg + redis if enabled)
├── next.config.ts
├── tsconfig.json
├── package.json
├── jest.config.js
└── README.md
Generation steps in order
Execute these steps sequentially. After each step, briefly confirm completion before moving on.
- Create root + directory tree.
mkdir -p the full tree.
- Write
package.json from assets/package.json.template, filling in dependencies based on choices. (Drop ioredis if cache=skip; drop resend if email=skip; etc.)
- Write
tsconfig.json (assets/tsconfig.json.template), next.config.ts (assets/next.config.ts.template), jest.config.js (assets/jest.config.js.template).
- Write
.eslintrc.json (assets/eslintrc.template) and .prettierrc.json (assets/prettierrc.template) — the verification gate uses both.
- Write
.gitignore from assets/gitignore.template.
- Write
prisma/schema.prisma from assets/prisma-schema.starter.prisma, swapping the datasource provider per the DB choice. Includes User / Session / Account / Verification / Role / Permission / RolePermission / UserRole / AuditLog / Example models out of the box.
- Write
src/env.ts from assets/env.ts.template, only including the env keys the project's enabled features need (drop REDIS_URL if cache=skip, etc.).
- Write
.env.example using references/env-example-template.md — block-assembled from feature flags.
- Write
src/server/db/client.ts from assets/db-client.ts.template.
- Write the auth scaffolding (if not skipped):
src/server/auth/index.ts from assets/auth-index.ts.template
src/server/auth/session.ts from assets/auth-session.ts.template
src/server/auth/permissions.ts from assets/auth-permissions.ts.template
src/lib/auth-client.ts from assets/auth-client.ts.template
src/app/(auth)/login/page.tsx from assets/login-page.tsx.template
src/app/api/auth/[...all]/route.ts from assets/api-auth-route.ts.template
- Write
src/server/lib/logger.ts (assets/logger.ts.template) and src/server/lib/errors.ts (assets/errors.ts.template).
- Write
src/server/modules/audit/audit.service.ts from assets/audit-service.ts.template so the example service's audit calls actually resolve.
- Write the service-layer scaffolding —
src/server/modules/_example/_example.service.ts (assets/example-service.ts.template) + _example.schema.ts (assets/example-schema.ts.template). Shows userId-first, permission check, audit-inside-transaction.
- Write the Server Action scaffolding —
src/server/actions/_example.actions.ts from assets/example-action.ts.template. Shows 'use server' + safeParse + revalidatePath + updateTag + redirect.
- Write the styling roots:
src/app/globals.css from assets/globals.css.template
postcss.config.mjs from assets/postcss.config.template
- (No
tailwind.config needed — Tailwind v4 reads @theme blocks from globals.css.)
- Write the root layout —
src/app/layout.tsx from assets/root-layout.tsx.template (imports globals.css, renders <html>/<body>, wires <Toaster />).
- Write the dashboard layout + home —
src/app/(dashboard)/layout.tsx from assets/dashboard-layout.tsx.template (calls requireSession(), renders sidebar)
src/app/(dashboard)/page.tsx from assets/dashboard-home-page.tsx.template
- Write the sample page tree —
src/app/(dashboard)/_example/page.tsx from assets/example-list-page.tsx.template and new/page.tsx from assets/example-new-page.tsx.template.
- Write the health route —
src/app/api/health/route.ts from assets/api-health-route.ts.template. This is the documented exception to Rule 1 (the route does a direct DB call — necessary for ALB / Caddy probes).
- Write the MCP route + registry + one example tool (if requested) — inline the code blocks from
nfs-add-mcp/SKILL.md into src/app/(mcp)/mcp/route.ts, src/server/mcp/registry.ts, src/server/mcp/tools/_example.ts, plus the two .well-known OAuth discovery routes. Add the three OAuth tables to prisma/schema.prisma. (The MCP files don't have assets/ templates — they live in the add-mcp skill as the canonical reference.)
- Write
instrumentation.ts (assets/instrumentation.ts.template) + src/server/jobs/index.ts (assets/jobs-index.ts.template) so cron registers once at boot.
- Write the seed + admin-bootstrap scripts —
prisma/seed.ts from assets/seed.ts.template (seeds default roles + permissions + role-permission joins)
prisma/grant-sysadmin.ts from assets/grant-sysadmin.ts.template (one-shot CLI to grant sysadmin after a user signs up)
- Write
Dockerfile (assets/dockerfile.template) + docker-compose.yml (assets/docker-compose.yml.template) if Docker deploy.
- Write
CLAUDE.md from assets/claude-md.template, substituting {{PROJECT_NAME}}, {{ONE_LINE_DESCRIPTION}}, {{DB_NAME}}, {{AUTH_BLOCK}}, {{DEPLOY_NOTE}}, {{DEPLOY_BLOCK}}. This is the contract for future Claude sessions.
- Write
docs/handoff.md from assets/handoff.md.template, substituting today's date and the per-feature state lines.
- Write
docs/architecture.md — copy from <plugin-root>/docs/architecture.md (at the plugin's root, not under any skill folder).
- Write
README.md from assets/readme.template.
git init + first commit chore: initial scaffold from nextjs-fullstack-starter. Tell the user explicitly: "I'm creating a nested independent git repo here — it's not a submodule of any outer repo."
- Verification step — run
pnpm install, pnpm prisma generate, pnpm tsc --noEmit, pnpm lint. Report results. Do not try to run migrations (no DB yet); the user owns that.
{{VARIABLE}} substitution reference
Many templates carry {{...}} slots. The full table:
| Variable |
Source / value |
{{PROJECT_NAME}} |
Q1 answer (e.g. inventory-tracker) |
{{PROJECT_NAME_SNAKE}} |
{{PROJECT_NAME}} with - → _ (e.g. inventory_tracker); used for DB names |
{{ONE_LINE_DESCRIPTION}} |
Asked separately or defaulted to "An internal back-office app." |
{{DB_NAME}} |
PostgreSQL / SQLite / MySQL (Q3) |
{{PRISMA_PROVIDER}} |
postgresql / sqlite / mysql (lowercase form for datasource db) |
{{AUTH_BLOCK}} |
Better Auth if enabled, (no auth wired yet — run /nfs-add-auth to add) if skipped |
{{AUTH_DEP}} |
better-auth if auth enabled, else removed from package.json |
{{AUTH_DEP_VERSION}} |
^1.0.0 (current major as of this plugin's release) |
{{DEPLOY_NOTE}} |
Self-hosted in Docker. / Deployed to Vercel. / empty |
{{DEPLOY_BLOCK}} |
Short paragraph describing the deploy setup matching the choice |
{{TODAY_ISO_DATE}} |
YYYY-MM-DD |
{{AUTH_STATE_LINE}} |
E.g. Better Auth wired. Credentials login at /login. or Auth skipped — run /nfs-add-auth to add. |
{{MCP_STATE_LINE}} |
E.g. MCP route at /mcp with one example tool. or MCP skipped. |
{{CACHE_STATE_LINE}} |
E.g. Using Next.js default cache. or Redis wired via src/server/lib/cache.ts. |
Key templates and references
The work is data-driven from the answers + these files:
references/stack-rationale.md — explains why this stack (read if user asks "why not X").
references/folder-structure.md — the canonical layout, expanded with comments.
references/claude-md-template.md — the CLAUDE.md template with variable slots.
references/env-example-template.md — the .env.example template, keyed by which optional features were enabled.
assets/*.template — actual file bodies to drop in, with {{VARIABLE}} slots.
When writing a file, read the corresponding template, substitute variables, then write. Don't generate from scratch — the templates carry hard-won decisions.
Post-scaffold
After the scaffold lands, point the user at the next moves:
pnpm dev to start the dev server.
- Edit
prisma/schema.prisma to add their first real model.
pnpm prisma migrate dev --name init to apply.
- Replace
_example with their first real business module — copy the shape verbatim.
/nfs-add-cache, /nfs-add-mcp, /nfs-add-auth to retrofit later.
- See
docs/architecture.md in the project for ongoing patterns.
Sanity guards
- Never overwrite an existing file without explicit confirmation. Always
ls the target directory first.
- Never run
pnpm install in the user's current directory if the project location is "new subdirectory" — cd into the new dir first.
- Never push to a remote automatically. The user owns that.
- Never invent dependencies — every dep in
package.json.template exists and is on a real version.
- Never skip the CLAUDE.md step — it's the most load-bearing file in the project's future, since every future Claude session reads it first.
- Never wire Server Actions without
revalidatePath or updateTag — the cache won't refresh and the user will think the action did nothing. The example action template demonstrates the right pattern; preserve it.
1---2name: nfs-scaffold-app3description: Scaffold a brand-new fullstack back-office app on pure Next.js (App Router) — Server Components for reads, Server Actions for writes, services in src/server/modules/. Use this whenever the user wants to start a new internal tool, admin dashboard, back-office app, line-of-business system, lightweight ERP, or CRUD app on Next.js without a separate API service — even if they don't name the stack. Walks the user through an interactive Q&A (project name, location, database, auth, cache, MCP, deployment target), then generates the canonical folder structure, dependencies, sample Server Action, sample service, Prisma schema starter, .env.example, and CLAUDE.md. Always trigger when the user wants a Next.js fullstack starter without tRPC, when they describe building a back office with Server Components, or when they say 'one Next.js app does everything'.4---56# Scaffold a new fullstack back-office app78This skill bootstraps a brand-new project on the **pure Next.js (App Router) fullstack** stack — no tRPC, no separate API service, no SPA shell. It is the entry point for the `nextjs-fullstack-starter` plugin and is invoked either explicitly via `/nfs-scaffold-app` or when the user expresses intent to start a new back-office system on plain Next.js.910## When to use this skill1112Use this skill when the user is **starting a brand-new project** in one of these shapes:1314- Internal admin dashboard / management system15- Back-office tool for staff16- Line-of-business app with CRUD over rich domain models17- Lightweight ERP / operational tool18- Solo or small-team SaaS where the main app is auth-walled19- Any "one Next.js app does everything" project2021Do NOT use this skill for:2223- Adding a feature to an existing project (those have their own skills — `nfs-add-auth`, `nfs-add-cache`, `nfs-add-mcp`).24- Projects where the user wants tRPC + SPA mode — use the sibling plugin `nextjs-trpc-prisma-starter` instead.25- Public-facing marketing sites or content sites where the patterns don't apply.26- Mobile-first products that need a typed HTTP API surface — Server Actions are web-only.2728## Why an interactive flow2930The stack is opinionated but the project has variables (database, auth provider, whether to wire cache from day one, MCP, deploy target). Asking up front means the generated project is **complete and consistent** rather than half-configured. The user can always add things later via the `nfs-add-*` skills.3132Use the `AskUserQuestion` tool for each step so the user gets a clean UI with options. Ask one question per call, not all at once — they shape later questions (e.g. answering "PostgreSQL" determines which Prisma adapter to install).3334## Conversation flow3536Walk the user through these questions in this order. Stop and confirm before any file write.3738### 1. Project name3940Open-ended. Validate: lowercase, hyphens-only, no spaces, valid as both a folder name and an npm package name.4142### 2. Project location4344Options:45- **New directory under current working directory** (e.g. `./<project-name>/`)46- **Use current working directory** (must be empty — check first with `ls -A`)47- **Custom absolute path**4849If "current directory" is chosen, run `ls -A` and abort if anything other than `.git/` is present. Don't overwrite the user's stuff.5051### 3. Database5253Options:54- **PostgreSQL (recommended)** — production default. Uses `@prisma/adapter-pg` driver.55- **SQLite** — for prototyping / very small deployments. No driver adapter needed.56- **MySQL** — if the team has existing MySQL infrastructure.5758Skip MongoDB — Prisma supports it but the patterns in `architecture-patterns` assume relational. Tell the user that if they ask.5960### 4. Auth6162Options:63- **Better Auth (recommended)** — modern, RBAC built-in, MCP plugin available, credentials + magic-link + OAuth providers.64- **Skip for now** — generate without auth wiring; user can run `/nfs-add-auth` later.6566Don't offer NextAuth here — Better Auth is the locked default for this stack because it integrates cleanly with the MCP plugin and has a simpler RBAC story. If the user pushes back, talk it through, but don't generate a NextAuth scaffold.6768### 5. Cache6970Options:71- **Next.js default cache (recommended for start)** — built-in `cacheTag` + `cacheLife` + `updateTag`. In-process. Fine until measurably not.72- **Add Redis on top** — wire `ioredis` + a Next.js cache handler from day one. Useful if multi-process / multi-deploy cache coherence matters.7374### 6. MCP entry point7576Options:77- **Yes (recommended)** — wires `/api/mcp/route.ts` with Better Auth's `mcp` plugin acting as OAuth provider. Adds one example tool. Requires Better Auth (from step 4) — if user skipped auth, warn and offer to enable both.78- **Skip** — easy to add later via `/nfs-add-mcp`.7980### 7. Deployment target8182Options:83- **Self-hosted Docker (e.g. on EC2)** — adds `Dockerfile`, `docker-compose.yml`, `next.config.ts` with `output: 'standalone'`.84- **Vercel** — adds `vercel.ts` config, no Dockerfile, adjusts a couple of patterns (e.g. cron via Vercel Crons instead of in-process `node-cron`).85- **Both / undecided** — adds the Docker bits but doesn't strip Vercel compat.8687### 8. Email / templates (optional)8889Options:90- **Skip**91- **Resend + Handlebars** — wires `src/server/integrations/resend/`, outbox pattern, retry cron.9293### 9. PDF generation (optional)9495Options:96- **Skip**97- **Gotenberg** — adds `src/server/integrations/gotenberg/` + `docker-compose.yml` service.9899### 10. Confirm100101Show a summary of all choices and the file/folder list that will be generated. User confirms or backs up.102103## Generated structure104105Files generated are derived from the answers plus the templates in `assets/`. The canonical layout is documented in `references/folder-structure.md` — read it before writing.106107Top level:108109```110<project-name>/111├── src/112│ ├── app/113│ │ ├── (auth)/login/page.tsx114│ │ ├── (dashboard)/115│ │ │ ├── layout.tsx # sidebar + requireSession()116│ │ │ ├── page.tsx # placeholder home117│ │ │ └── _example/ # sample CRUD page (list + new + [id])118│ │ ├── (mcp)/mcp/route.ts # if MCP=yes119│ │ ├── api/120│ │ │ ├── auth/[...all]/route.ts # if Better Auth121│ │ │ ├── health/route.ts122│ │ │ └── webhooks/ # placeholder folder123│ │ ├── layout.tsx124│ │ └── globals.css125│ ├── server/126│ │ ├── db/client.ts127│ │ ├── auth/128│ │ │ ├── index.ts129│ │ │ ├── session.ts # requireSession()130│ │ │ └── permissions.ts # requirePermission()131│ │ ├── modules/132│ │ │ └── _example/ # sample service + schema133│ │ │ ├── _example.service.ts134│ │ │ └── _example.schema.ts135│ │ ├── actions/136│ │ │ └── _example.actions.ts # sample Server Action137│ │ ├── jobs/ # cron registration138│ │ │ └── index.ts139│ │ ├── lib/140│ │ │ ├── logger.ts141│ │ │ ├── errors.ts142│ │ │ └── cache.ts # if cache=Redis143│ │ ├── mcp/ # if MCP=yes144│ │ │ ├── registry.ts145│ │ │ └── tools/_example.ts146│ │ └── integrations/ # placeholder folder147│ ├── components/ui/ # shadcn primitives (added as needed)148│ ├── lib/utils.ts149│ ├── hooks/150│ └── env.ts # @t3-oss/env-nextjs151├── prisma/152│ ├── schema.prisma153│ ├── migrations/154│ └── seed.ts155├── tests/156│ └── e2e/ # Playwright placeholder157├── public/158├── docs/159│ ├── handoff.md # session-handoff doc (start-here for Claude)160│ └── architecture.md # link to plugin's docs/161├── instrumentation.ts # boots cron in production162├── .env.example163├── .gitignore164├── CLAUDE.md # generated, reflects choices165├── Dockerfile # if deploy=docker166├── docker-compose.yml # postgres + (gotenberg + redis if enabled)167├── next.config.ts168├── tsconfig.json169├── package.json170├── jest.config.js171└── README.md172```173174## Generation steps in order175176Execute these steps sequentially. After each step, briefly confirm completion before moving on.1771781. **Create root + directory tree.** `mkdir -p` the full tree.1792. **Write `package.json`** from `assets/package.json.template`, filling in dependencies based on choices. (Drop `ioredis` if cache=skip; drop `resend` if email=skip; etc.)1803. **Write `tsconfig.json`** (`assets/tsconfig.json.template`), **`next.config.ts`** (`assets/next.config.ts.template`), **`jest.config.js`** (`assets/jest.config.js.template`).1814. **Write `.eslintrc.json`** (`assets/eslintrc.template`) and **`.prettierrc.json`** (`assets/prettierrc.template`) — the verification gate uses both.1825. **Write `.gitignore`** from `assets/gitignore.template`.1836. **Write `prisma/schema.prisma`** from `assets/prisma-schema.starter.prisma`, swapping the datasource provider per the DB choice. Includes User / Session / Account / Verification / Role / Permission / RolePermission / UserRole / AuditLog / Example models out of the box.1847. **Write `src/env.ts`** from `assets/env.ts.template`, only including the env keys the project's enabled features need (drop `REDIS_URL` if cache=skip, etc.).1858. **Write `.env.example`** using `references/env-example-template.md` — block-assembled from feature flags.1869. **Write `src/server/db/client.ts`** from `assets/db-client.ts.template`.18710. **Write the auth scaffolding** (if not skipped):188 - `src/server/auth/index.ts` from `assets/auth-index.ts.template`189 - `src/server/auth/session.ts` from `assets/auth-session.ts.template`190 - `src/server/auth/permissions.ts` from `assets/auth-permissions.ts.template`191 - `src/lib/auth-client.ts` from `assets/auth-client.ts.template`192 - `src/app/(auth)/login/page.tsx` from `assets/login-page.tsx.template`193 - `src/app/api/auth/[...all]/route.ts` from `assets/api-auth-route.ts.template`19411. **Write `src/server/lib/logger.ts`** (`assets/logger.ts.template`) and **`src/server/lib/errors.ts`** (`assets/errors.ts.template`).19512. **Write `src/server/modules/audit/audit.service.ts`** from `assets/audit-service.ts.template` so the example service's audit calls actually resolve.19613. **Write the service-layer scaffolding** — `src/server/modules/_example/_example.service.ts` (`assets/example-service.ts.template`) + `_example.schema.ts` (`assets/example-schema.ts.template`). Shows `userId`-first, permission check, audit-inside-transaction.19714. **Write the Server Action scaffolding** — `src/server/actions/_example.actions.ts` from `assets/example-action.ts.template`. Shows `'use server'` + safeParse + `revalidatePath` + `updateTag` + `redirect`.19815. **Write the styling roots:**199 - `src/app/globals.css` from `assets/globals.css.template`200 - `postcss.config.mjs` from `assets/postcss.config.template`201 - (No `tailwind.config` needed — Tailwind v4 reads `@theme` blocks from `globals.css`.)20216. **Write the root layout** — `src/app/layout.tsx` from `assets/root-layout.tsx.template` (imports `globals.css`, renders `<html>`/`<body>`, wires `<Toaster />`).20317. **Write the dashboard layout + home** —204 - `src/app/(dashboard)/layout.tsx` from `assets/dashboard-layout.tsx.template` (calls `requireSession()`, renders sidebar)205 - `src/app/(dashboard)/page.tsx` from `assets/dashboard-home-page.tsx.template`20618. **Write the sample page tree** — `src/app/(dashboard)/_example/page.tsx` from `assets/example-list-page.tsx.template` and `new/page.tsx` from `assets/example-new-page.tsx.template`.20719. **Write the health route** — `src/app/api/health/route.ts` from `assets/api-health-route.ts.template`. This is the documented exception to Rule 1 (the route does a direct DB call — necessary for ALB / Caddy probes).20820. **Write the MCP route + registry + one example tool** (if requested) — inline the code blocks from `nfs-add-mcp/SKILL.md` into `src/app/(mcp)/mcp/route.ts`, `src/server/mcp/registry.ts`, `src/server/mcp/tools/_example.ts`, plus the two `.well-known` OAuth discovery routes. Add the three OAuth tables to `prisma/schema.prisma`. (The MCP files don't have `assets/` templates — they live in the add-mcp skill as the canonical reference.)20921. **Write `instrumentation.ts`** (`assets/instrumentation.ts.template`) + **`src/server/jobs/index.ts`** (`assets/jobs-index.ts.template`) so cron registers once at boot.21022. **Write the seed + admin-bootstrap scripts** —211 - `prisma/seed.ts` from `assets/seed.ts.template` (seeds default roles + permissions + role-permission joins)212 - `prisma/grant-sysadmin.ts` from `assets/grant-sysadmin.ts.template` (one-shot CLI to grant sysadmin after a user signs up)21323. **Write `Dockerfile`** (`assets/dockerfile.template`) + **`docker-compose.yml`** (`assets/docker-compose.yml.template`) if Docker deploy.21424. **Write `CLAUDE.md`** from `assets/claude-md.template`, substituting `{{PROJECT_NAME}}`, `{{ONE_LINE_DESCRIPTION}}`, `{{DB_NAME}}`, `{{AUTH_BLOCK}}`, `{{DEPLOY_NOTE}}`, `{{DEPLOY_BLOCK}}`. This is the contract for future Claude sessions.21525. **Write `docs/handoff.md`** from `assets/handoff.md.template`, substituting today's date and the per-feature state lines.21626. **Write `docs/architecture.md`** — copy from `<plugin-root>/docs/architecture.md` (at the plugin's root, not under any skill folder).21727. **Write `README.md`** from `assets/readme.template`.21828. **`git init`** + first commit `chore: initial scaffold from nextjs-fullstack-starter`. Tell the user explicitly: "I'm creating a nested independent git repo here — it's not a submodule of any outer repo."21929. **Verification step** — run `pnpm install`, `pnpm prisma generate`, `pnpm tsc --noEmit`, `pnpm lint`. Report results. Do not try to run migrations (no DB yet); the user owns that.220221### `{{VARIABLE}}` substitution reference222223Many templates carry `{{...}}` slots. The full table:224225| Variable | Source / value |226|---|---|227| `{{PROJECT_NAME}}` | Q1 answer (e.g. `inventory-tracker`) |228| `{{PROJECT_NAME_SNAKE}}` | `{{PROJECT_NAME}}` with `-` → `_` (e.g. `inventory_tracker`); used for DB names |229| `{{ONE_LINE_DESCRIPTION}}` | Asked separately or defaulted to `"An internal back-office app."` |230| `{{DB_NAME}}` | `PostgreSQL` / `SQLite` / `MySQL` (Q3) |231| `{{PRISMA_PROVIDER}}` | `postgresql` / `sqlite` / `mysql` (lowercase form for `datasource db`) |232| `{{AUTH_BLOCK}}` | `Better Auth` if enabled, `(no auth wired yet — run /nfs-add-auth to add)` if skipped |233| `{{AUTH_DEP}}` | `better-auth` if auth enabled, else removed from `package.json` |234| `{{AUTH_DEP_VERSION}}` | `^1.0.0` (current major as of this plugin's release) |235| `{{DEPLOY_NOTE}}` | `Self-hosted in Docker.` / `Deployed to Vercel.` / empty |236| `{{DEPLOY_BLOCK}}` | Short paragraph describing the deploy setup matching the choice |237| `{{TODAY_ISO_DATE}}` | `YYYY-MM-DD` |238| `{{AUTH_STATE_LINE}}` | E.g. `Better Auth wired. Credentials login at /login.` or `Auth skipped — run /nfs-add-auth to add.` |239| `{{MCP_STATE_LINE}}` | E.g. `MCP route at /mcp with one example tool.` or `MCP skipped.` |240| `{{CACHE_STATE_LINE}}` | E.g. `Using Next.js default cache.` or `Redis wired via src/server/lib/cache.ts.` |241242## Key templates and references243244The work is data-driven from the answers + these files:245246- `references/stack-rationale.md` — explains why this stack (read if user asks "why not X").247- `references/folder-structure.md` — the canonical layout, expanded with comments.248- `references/claude-md-template.md` — the `CLAUDE.md` template with variable slots.249- `references/env-example-template.md` — the `.env.example` template, keyed by which optional features were enabled.250- `assets/*.template` — actual file bodies to drop in, with `{{VARIABLE}}` slots.251252When writing a file, read the corresponding template, substitute variables, then write. Don't generate from scratch — the templates carry hard-won decisions.253254## Post-scaffold255256After the scaffold lands, point the user at the next moves:257258- `pnpm dev` to start the dev server.259- Edit `prisma/schema.prisma` to add their first real model.260- `pnpm prisma migrate dev --name init` to apply.261- Replace `_example` with their first real business module — copy the shape verbatim.262- `/nfs-add-cache`, `/nfs-add-mcp`, `/nfs-add-auth` to retrofit later.263- See `docs/architecture.md` in the project for ongoing patterns.264265## Sanity guards266267- **Never overwrite an existing file** without explicit confirmation. Always `ls` the target directory first.268- **Never run `pnpm install` in the user's current directory** if the project location is "new subdirectory" — `cd` into the new dir first.269- **Never push to a remote** automatically. The user owns that.270- **Never invent dependencies** — every dep in `package.json.template` exists and is on a real version.271- **Never skip the CLAUDE.md step** — it's the most load-bearing file in the project's future, since every future Claude session reads it first.272- **Never wire Server Actions without `revalidatePath` or `updateTag`** — the cache won't refresh and the user will think the action did nothing. The example action template demonstrates the right pattern; preserve it.