From nextjs-starter
Scaffold a production-ready Next.js project with App Router, TypeScript, Tailwind 4, shadcn/ui, and opinionated project structure. Use when the user asks to create a new Next.js project, start a new web app, or bootstrap a frontend application.
How this skill is triggered — by the user, by Claude, or both
Slash command
/nextjs-starter:nextjs-starterThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Scaffolds a complete, opinionated Next.js project with interactive customization. Generates project structure, installs dependencies, configures tooling, writes architecture rules in CLAUDE.md, and makes an initial commit.
Scaffolds a complete, opinionated Next.js project with interactive customization. Generates project structure, installs dependencies, configures tooling, writes architecture rules in CLAUDE.md, and makes an initial commit.
6 phases executed sequentially:
Ask the user 4 questions using AskUserQuestion. Store the answers as variables for use in later phases.
AskUserQuestion(
question: "What is the name of your project?",
type: "free_text"
)
Store as PROJECT_NAME.
AskUserQuestion(
question: "Which package manager would you like to use?",
type: "single_select",
options: [
{ value: "pnpm", label: "pnpm (recommended)" },
{ value: "npm", label: "npm" },
{ value: "bun", label: "bun" }
]
)
Store as PM. Derive the following variables from PM:
PM | PM_RUN | PM_DLX | PM_CREATE | PM_FLAG |
|---|---|---|---|---|
pnpm | pnpm | pnpm dlx | pnpm create | --use-pnpm |
npm | npm run | npx | npx | --use-npm |
bun | bun | bunx | bunx | --use-bun |
AskUserQuestion(
question: "Which extras would you like to include?",
type: "multi_select",
options: [
{ value: "husky", label: "husky + lint-staged (recommended)" },
{ value: "commitlint", label: "commitlint (recommended)" },
{ value: "editorconfig",label: ".editorconfig (recommended)" },
{ value: "vscode", label: "VS Code settings (recommended)" },
{ value: "env_example", label: ".env.example (recommended)" }
]
)
Store as EXTRAS (list of selected values).
AskUserQuestion(
question: "Which MCPs would you like to configure? (Context7 is always included)",
type: "multi_select",
options: [
{ value: "context7", label: "Context7 (always included)" },
{ value: "figma", label: "Figma MCP" },
{ value: "browser_preview",label: "Browser Preview" },
{ value: "other", label: "Other (you will be prompted for details)" }
]
)
Store as MCPS (list of selected values). context7 is always included regardless of selection. If other is selected, ask a follow-up free-text question to capture the additional MCP details.
Before proceeding, check if the selected package manager (PM) is installed:
command -v {PM}
If the command is not found (exit code ≠ 0) and PM is pnpm or bun:
AskUserQuestion(
question: "{PM} is not installed. Would you like me to install it?",
type: "single_select",
options: [
{ value: "yes", label: "Yes, install {PM}" },
{ value: "no", label: "No, switch to npm instead" }
]
)
pnpm: npm install -g pnpmbun: curl -fsSL https://bun.sh/install | bashPM to npm and re-derive all PM variables (PM_RUN, PM_DLX, PM_CREATE, PM_FLAG).If PM is npm, skip this check — npm is always available with Node.js.
{PM_CREATE} next-app {PROJECT_NAME} --typescript --tailwind --eslint --app --src-dir --import-alias "@/*" {PM_FLAG}
Then cd into the project directory:
cd {PROJECT_NAME}
Detect the current Node.js version:
node -v
Store the output (e.g., v22.14.0) as NODE_VERSION (without the v prefix → 22.14.0). Extract the major version as NODE_MAJOR (e.g., 22).
Write .nvmrc at the project root:
{NODE_MAJOR}
Add the engines field to package.json:
"engines": {
"node": ">={NODE_MAJOR}"
}
src/app/page.tsxWrite this exact content:
export default function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-center">
<h1 className="text-4xl font-bold">Welcome</h1>
</main>
);
}
src/app/globals.cssKeep only Tailwind directives and CSS variables. Remove all other default styles generated by create-next-app.
public/Delete any default images (e.g., next.svg, vercel.svg) from the public/ directory.
Initialize shadcn/ui (choose style: default, base color: neutral, CSS variables: yes):
{PM_DLX} shadcn@latest init
Add the button component:
{PM_DLX} shadcn@latest add button
Install Prettier and the Tailwind plugin:
{PM} add -D prettier prettier-plugin-tailwindcss
Write .prettierrc:
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"tabWidth": 2,
"printWidth": 80,
"plugins": ["prettier-plugin-tailwindcss"]
}
Add a format script to package.json:
"format": "prettier --write ."
Verify tsconfig.json has "strict": true and the @/* path alias. create-next-app generates these — just confirm they are present.
Detect the ESLint config format:
eslint.config.mjs.eslintrc.jsonExtend the detected config with import ordering rules.
Detect Tailwind version:
@theme block lives in globals.css. Configure the shadcn theme there.tailwind.config.ts. Configure the shadcn theme in that file.Apply only the extras present in EXTRAS.
husky in EXTRAS)Detect husky version and initialize accordingly:
{PM_DLX} husky init{PM_DLX} husky-initConfigure .husky/pre-commit to run:
{PM_DLX} lint-staged
Write .lintstagedrc.json:
{
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{json,md,css}": ["prettier --write"]
}
commitlint in EXTRAS){PM} add -D @commitlint/cli @commitlint/config-conventional commitizen cz-conventional-changelog
Write commitlint.config.js:
module.exports = { extends: ['@commitlint/config-conventional'] };
Add commitizen config to package.json:
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
Add a commit script to package.json:
"commit": "cz"
If husky is also selected, add a commit-msg hook that runs commitlint.
editorconfig in EXTRAS)Write .editorconfig:
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
vscode in EXTRAS)Write .vscode/settings.json:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.quickSuggestions": {
"strings": true
},
"css.validate": false,
"tailwindCSS.experimental.classRegex": []
}
Write .vscode/extensions.json:
{
"recommendations": [
"bradlc.vscode-tailwindcss",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint"
]
}
env_example in EXTRAS)Write .env.example:
NEXT_PUBLIC_APP_URL=http://localhost:3000
DATABASE_URL=
NEXT_PUBLIC_API_URL=
Run these commands to create the project layout:
mkdir -p src/components/shared src/features src/hooks src/lib src/types
touch src/components/shared/.gitkeep src/features/.gitkeep src/hooks/.gitkeep src/types/.gitkeep
Note: src/components/ui/ and src/lib/utils.ts already exist — they were created by shadcn init in Phase 3. Do not recreate or modify them.
Write CLAUDE.md at the project root with the following content, substituting {PROJECT_NAME}, {PM}, {PM_RUN}, and {PM_DLX}:
# {PROJECT_NAME}
## Stack
Next.js (App Router), TypeScript, Tailwind 4, shadcn/ui, {PM}
## Architecture Rules
### Folder Structure
- `app/` - ONLY routes, layouts, loading, error. Zero business logic
- `components/ui/` - Managed by shadcn CLI. NEVER create/edit manually
- `components/shared/` - Reusable components, ALWAYS composed from ui/
- `features/<name>/` - Self-contained: components/, hooks/, lib/, types/
- `lib/` - Pure functions, clients, configs. No React components
- `hooks/` - Global hooks. Feature hooks live in features/<name>/hooks/
- `types/` - Types shared between features
### Component Rules
- Every visual component MUST use primitives from components/ui/
- NEVER use native <button>, <input>, <select> - use shadcn
- Add new ui components: `{PM_DLX} shadcn@latest add <name>`
- Components MUST be reusable. Extract when used 2+ times
- Props typed with interfaces, never any
### Code Rules
- Path aliases: use @/ for all imports (never ../../../)
- Exports: named exports only (never default export except pages)
- Server Components by default. Use "use client" only when necessary
- Pure functions in lib/. Side effects isolated in hooks
### Commit Messages (Conventional Commits)
- Format: `<type>(<scope>): <description>`
- Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
- Scope is optional but recommended (e.g., `feat(auth): add login page`)
- Description: imperative mood, lowercase, no period at end
- Breaking changes: add `!` after type/scope (e.g., `feat!: remove legacy API`)
- Use `{PM_RUN} commit` for interactive commit wizard (commitizen)
## Required Skills
- USE superpowers:brainstorming BEFORE creating any new feature
- USE frontend-design when creating visual components and pages
- USE superpowers:writing-plans for features touching more than 2 files
- USE superpowers:verification-before-completion before declaring tasks done
## Commands
- `{PM_RUN} dev` - dev server
- `{PM_RUN} build` - production build
- `{PM_RUN} lint` - ESLint
- `{PM_RUN} format` - Prettier
- `{PM_RUN} commit` - interactive commit (commitizen)
Write .mcp.json at the project root. Context7 is always included:
{
"mcpServers": {
"context7": {
"command": "npx",
"args": ["-y", "@upstash/context7-mcp@latest"]
}
}
}
For each MCP in MCPS, extend mcpServers:
figma (if figma in MCPS): add entry:
"figma": {
"command": "npx",
"args": ["-y", "@anthropic-ai/figma-mcp@latest"]
}
browser_preview (if browser_preview in MCPS): inform the user that Browser Preview is configured in Claude Code settings, not in .mcp.json. No entry needed here.
other (if other in MCPS): use the command/args captured from the follow-up question in Q4 and add the entry to .mcp.json.
{PM_RUN} build
If it fails, read the error output, fix the issues, and retry. Maximum 3 attempts. Stop and report to the user if it still fails after 3 attempts.
{PM_RUN} lint
If it fails, read the error output, fix the issues, and retry. Maximum 3 attempts. Stop and report to the user if it still fails after 3 attempts.
Initialize a git repo if one does not already exist:
git init
Stage all files and create the initial commit:
git add .
git commit -m "feat: scaffold project with Next.js, Tailwind 4, shadcn/ui
- App Router with TypeScript strict mode
- shadcn/ui component library (Radix + Tailwind)
- Prettier + ESLint configured
- Opinionated folder structure (hybrid: layer + feature)
- CLAUDE.md with architecture rules
- MCP configuration (Context7 + extras)"
Project {PROJECT_NAME} created successfully.
- X files generated
- Build: OK | Lint: OK
- Extras: {list of extras}
- MCPs: {list of MCPs}
- Initial commit created
Next step: cd {PROJECT_NAME} && {PM_RUN} dev
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub strapazzon/skill-nextjs-starter --plugin nextjs-starter