# Next.js 16 Template ![Next.js 16 - a modern template repo](docs/images/nextjs-hero.png) *A Next.js 16.4 template. Lint, format, type and unit-test checks run on every commit, and end-to-end tests on every push. Every PR repeats these checks on GitHub and adds end-to-end tests against a Vercel Preview. A branch ruleset ([one-time setup](docs/project-setup.md)) blocks merging to `main` until they pass. Merging deploys to Vercel Production, where the end-to-end tests run again. Dependabot opens PRs automatically for security fixes and GitHub Actions updates. Claude Code is set up, plugins included. [You choose the rest](#you-choose-the-rest): UI components, database, etc.*
Template homepage in light and dark mode

Template homepage โ€” deployed on Vercel

## ๐ŸŽฏ Use This Template **Prerequisites:** [Claude Code](https://code.claude.com), [Git](https://git-scm.com), [GitHub CLI](https://cli.github.com) (logged in via `gh auth login`) and [Node.js 26](https://nodejs.org) for Next.js. To check and install them, give Claude Code [this README](https://raw.githubusercontent.com/michellepace/nextjs-template/refs/heads/main/README.md) and ask it to install only the missing prerequisites.
(1) Get the Code โ€” fresh start or keep history Pick one, swapping `my-app` for your new repository name: ```bash # Fresh start, no template history (same as the "Use this template" button) gh repo create my-app --template michellepace/nextjs-template --public --clone cd my-app ``` ```bash # Keep history: Claude can read the template's commits to answer "why was this done?" git clone https://github.com/michellepace/nextjs-template.git my-app cd my-app git remote remove origin gh repo create my-app --public --source . --push git remote set-head origin --auto # record main as default, as a clone does ``` Keep `--public` unless you have GitHub Pro โ€” free accounts can't protect `main` on private repos.
(2) Install and Run โ€” dependencies, test browsers, dev server ```bash npm install # Dependencies + git hooks npx playwright install chromium webkit --with-deps # Browsers for E2E tests npm run dev # Open http://localhost:3000 (Ctrl+C to stop) ```
(3) Set Up Claude Code โ€” global tools and plugins Install the tools Claude Code's TypeScript plugin and browser skill need: ```bash # typescript-lsp plugin runs this. It then uses the project's TypeScript npm install -g typescript-language-server # Browser automation for Claude. Rerun both lines to upgrade the CLI: # the second line rewrites .claude/skills/playwright-cli/ to match it npm install -g @playwright/cli@latest playwright-cli install --skills ``` Then run `claude` in the project folder, trust it, and accept the offer to install the plugins in [`.claude/settings.json`](.claude/settings.json). If you skipped the offer, run: ```bash claude plugin marketplace add anthropics/claude-plugins-official --scope project claude plugin marketplace add michellepace/my-claude-marketplace --scope project claude plugin install typescript-lsp@claude-plugins-official --scope project claude plugin install alwayson-misc@my-claude-marketplace --scope project claude plugin install git-utils@my-claude-marketplace --scope project claude plugin install mattpocock-skills@claude-plugins-official --scope project # enable claude plugin disable mattpocock-skills@claude-plugins-official --scope project # disable again ``` - **mattpocock-skills** is disabled: its many skills fill the context window and trigger when you don't want them. Turn it on with `claude plugin enable mattpocock-skills@claude-plugins-official --scope project`. - **[git-utils](https://github.com/michellepace/my-claude-marketplace/tree/main/plugins/git-utils)** is my own plugin and optional. Ask Claude to remove or disable it.
(4) Install Extensions โ€” VS Code / Cursor In VS Code or Cursor, install the extensions listed in [`.vscode/extensions.json`](.vscode/extensions.json). When the editor asks to use the workspace TypeScript version, click Allow โ€” this turns on the Next.js editor checks. Missed it? Open a `.tsx` file, press Ctrl+Shift+P and run **TypeScript: Select TypeScript Version** โ†’ **Use Workspace Version**.
(5) GitHub + Vercel Setup โ€” deploys, CI, branch protection Follow [`docs/project-setup.md`](docs/project-setup.md) to set up GitHub and Vercel.
(6) Housekeeping โ€” make the Claude Code config yours Modify [`.claude/CLAUDE.md`](.claude/CLAUDE.md), [`.mcp.json`](.mcp.json), and [`.claude/settings.json`](.claude/settings.json) (permissions and plugins) as preferred.
(7) Choose UI Library โ€” shadcn/ui, HeroUI or Tailwind Plus Choose one that supports Tailwind 4. [shadcn/ui](https://ui.shadcn.com/) (free) and [HeroUI v3](https://heroui.com/) (free) are both LLM friendly and use semantic tokens โ€” which makes theming easy. shadcn is ubiquitous so theme it well to stand out โ€” [tweak-cn](https://tweakcn.com/) and [theme-generator](https://shadcnstudio.com/theme-generator) are helpful. HeroUI is more visually distinct and extremely LLM friendly; it ships with agent skills too. [Tailwind Plus](https://tailwindcss.com/plus) (paid) offers components ([Catalyst](https://tailwindcss.com/plus/ui-kit)), assembled UI blocks, and full site templates, but doesn't include semantic tokens so centralised theming takes more manual work.
(8) Decide on Icons โ€” each UI library ships its own Each UI library above ships with icons โ€” shadcn/ui uses [Lucide React](https://lucide.dev/guide/react/), Tailwind Plus (Catalyst) uses [Heroicons](https://heroicons.com/), HeroUI uses [Iconify](https://iconify.design/). All three let you swap to a different icon library.
(9) Replace Template Files โ€” your pages, theme and fonts Replace [`app/page.tsx`](app/page.tsx), [`app/layout.tsx`](app/layout.tsx), [`components/button.tsx`](components/button.tsx), [`app/globals.css`](app/globals.css) (centralised theming), [`app/fonts.ts`](app/fonts.ts), and [`components/theme-toggle.tsx`](components/theme-toggle.tsx) (use an icon).
## What's Installed? For exact list see [`package.json`](package.json) | Category | Tool | What it does | | :------- | :--- | :----------- | | Runtime | [Node.js 26 LTS](https://nodejs.org) | Major version set in [`.nvmrc`](.nvmrc), and in `engines` and `@types/node` in [`package.json`](package.json); raise all three together | | Framework | [Next.js 16.4](https://nextjs.org) | Core webapp foundation โ€” routing, rendering, API routes, optimisation, and builds | | Language | [TypeScript 6](https://www.typescriptlang.org) | Static type checking with strict mode enabled โ€” not 7 yet, which can't run the Next.js editor plugin | | Styling | [Tailwind CSS v4](https://tailwindcss.com) | Utility-first CSS framework for rapid styling | | | [next-themes](https://github.com/pacocoursey/next-themes) | Light/dark mode theming provider | | Linting | [Biome](https://biomejs.dev) | Fast linter and formatter (replaces ESLint + Prettier) | | | [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) | Lints markdown files for consistent formatting | | Testing | [Vitest](https://vitest.dev) | Fast unit test runner (Vite-native, Jest-compatible) | | | [Playwright](https://playwright.dev) | E2E browser testing (Chromium, Mobile Safari) | | | [Testing Library](https://testing-library.com) | React component testing utilities | | Git Hooks | [Lefthook](https://lefthook.dev) | Runs checks on commit (lint, typecheck, unit tests) and push (build, E2E tests) | | Optimisation | [React Compiler](https://react.dev/learn/react-compiler) | Automatic memoisation and performance optimisations | | Analytics | [Vercel Speed Insights](https://vercel.com/docs/speed-insights) | Real user performance metrics viewable on Vercel | | | [Vercel Web Analytics](https://vercel.com/docs/analytics) | Privacy-friendly visitor analytics viewable on Vercel | ## You Choose the Rest You'll need: - UI components (e.g. shadcn/ui, HeroUI v3, Tailwind Plus) - Database/ORM (e.g. Neon or Supabase with Prisma or Drizzle. Or Convex - no ORM needed!) - Authentication (e.g. Clerk, Supabase Auth, or Better Auth โ€” open source, Vercel-owned) - Validation (e.g. Zod, to check form and API data on the server) Maybe: - Forms (e.g. React Hook Form, for complex forms) - State management (e.g. Zustand, Jotai, or React Context) ## This Repo Explained
Next.js Installation โ€” the create-next-app answers This template was initialised with the following options: ```bash # Next.js installer $ npx create-next-app@latest Would you like to use TypeScript? โœ”๏ธ Yes Which linter would you like to use? โœ”๏ธ Biome Would you like to use React Compiler? โœ”๏ธ Yes Would you like to use Tailwind CSS? โœ”๏ธ Yes Would you like your code inside a src/ directory? โŒ No Would you like to use App Router? (recommended) โœ”๏ธ Yes Would you like to use Cache Components? โœ”๏ธ Yes Would you like to customise the import alias (@/* by default)? โŒ No Would you like to include AGENTS.md to guide coding agents? โœ”๏ธ Yes Would you like to help improve Next.js by letting agents prepare anonymised feedback? โŒ No ```
Config Files โ€” what each one does *Key: ๐ŸŒบ Claude Code ยท ๐Ÿ…ฝ Next.js ยท ๐Ÿงช Checks and tests ยท ๐Ÿš€ GitHub CI/CD* | File | What it does | | :----- | :----- | | ๐ŸŒบ [`.claude/rules/`](.claude/rules/) | Claude Code rules, loaded only when Claude works with matching file paths | | ๐ŸŒบ [`.claude/CLAUDE.md`](.claude/CLAUDE.md) | Claude Code project instructions: tech stack, conventions, traps and commands (customise!) | | ๐ŸŒบ [`.claude/settings.json`](.claude/settings.json) | Claude Code project settings: allow/deny permissions, enabled plugins and marketplaces | | ๐Ÿš€ [`.github/workflows/check-lint-type.yml`](.github/workflows/check-lint-type.yml) | CI workflow: runs Biome and TypeScript checks on every PR; must pass to merge | | ๐Ÿš€ [`.github/workflows/test-e2e-vercel.yml`](.github/workflows/test-e2e-vercel.yml) | CI workflow: runs Playwright E2E tests against each live Vercel deploy, to catch what only breaks on Vercel; Preview must pass to merge, Production is checked after merge (can't block) | | ๐Ÿš€ [`.github/workflows/test-e2e.yml`](.github/workflows/test-e2e.yml) | CI workflow: builds for production and runs Playwright E2E tests on every PR; must pass to merge | | ๐Ÿš€ [`.github/workflows/test-unit.yml`](.github/workflows/test-unit.yml) | CI workflow: runs Vitest unit tests on every PR; must pass to merge | | ๐Ÿš€ [`.github/dependabot.yml`](.github/dependabot.yml) | Dependabot config: weekly PRs to update GitHub Actions | | ๐Ÿงช [`.playwright/`](.playwright/) | Playwright test outputs (`test-results/`, `playwright-report/`), kept here instead of project root, plus `cli.config.json` for playwright-cli | | ๐ŸŒบ `.playwright-cli/` | playwright-cli output: page snapshots and screenshots Claude takes when it drives a browser (git-ignored) | | [`.vscode/extensions.json`](.vscode/extensions.json) | Recommended VS Code extensions, so your editor uses this repo's tools: lint and format, Tailwind autocomplete, etc. | | [`.vscode/settings.json`](.vscode/settings.json) | VS Code workspace settings: Biome format on save, Tailwind IntelliSense, the project's TypeScript | | [`.gitattributes`](.gitattributes) | Git line-ending rules, so diffs match across platforms (Windows, macOS, Linux) | | [`.gitignore`](.gitignore) | Files Git ignores: dependencies, build output, test output, secrets, etc. | | ๐Ÿงช [`.markdownlint-cli2.yaml`](.markdownlint-cli2.yaml) | Markdown linter config: rules to switch off and files to skip when checking markdown files | | ๐ŸŒบ [`.mcp.json`](.mcp.json) | Claude Code MCP servers: Ref, for docs search (optional; set API key in `API_KEY_MCP_REF` environment variable) | | [`.nvmrc`](.nvmrc) | Node.js version pin: CI and `nvm use` read it, so your machine and CI run the same Node major | | ๐Ÿงช [`biome.jsonc`](biome.jsonc) | Biome config: one set of lint and format rules, used by your editor on save, git hooks and CI | | ๐Ÿงช [`lefthook.yml`](lefthook.yml) | Git hooks config: lint, typecheck and unit tests on commit; build and E2E tests on push, so most problems are caught before CI | | ๐Ÿ…ฝ [`next.config.ts`](next.config.ts) | Next.js config: React Compiler, Cache Components, partial prefetching, typed routes | | ๐Ÿ…ฝ [`package.json`](package.json) | Packages the app uses and the versions each may update to, npm scripts, and the allowed Node versions | | ๐Ÿงช [`playwright.config.ts`](playwright.config.ts) | Playwright E2E test config: browsers to test in, and the site to test (local server or a Vercel deployment) | | ๐Ÿ…ฝ [`postcss.config.mjs`](postcss.config.mjs) | PostCSS config: runs Tailwind on your CSS (the theme lives in `app/globals.css`) | | ๐Ÿงช [`tsconfig.json`](tsconfig.json) | TypeScript config: strict type checking, and `@/` imports that start from the project root | | ๐Ÿงช [`vitest.config.ts`](vitest.config.ts) | Vitest unit test config: tests run in a simulated browser (jsdom), with React Compiler on as in the app | | ๐Ÿงช [`vitest.setup.ts`](vitest.setup.ts) | Vitest setup file: runs before each test file; holds shared test setup |
CI/CD Workflow โ€” from first commit to production ```text โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ๐Ÿ’ป LAPTOP: Create a new branch (tests on local dev machine) โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ git checkout -b feature/add-dark-mode โ”‚ โ”œโ”€ Commit 1: Add light/dark mode โšก pre-commit hook runs โ”‚ โ”œโ”€ ๐ŸŽจ Biome lint and format โœ… Auto-fixed & staged โ”‚ โ”œโ”€ ๐Ÿ” TypeScript type check โœ… Pass โ”‚ โ””โ”€ ๐Ÿงช Vitest unit tests โœ… Pass โ”‚ (then committed on all pass) โ”‚ โ”œโ”€ Commit 2: (some more work here) โšก pre-commit hook runs again โ”‚ โ””โ”€ Commit 3: (some more work here) โšก pre-commit hook runs again (optional) /simplify, /code-review, /security-review before pushing see docs/project-setup.md ยง Checking Quality git push origin feature/add-dark-mode โšก pre-PUSH hook runs โ”œโ”€ ๐Ÿ—๏ธ Next.js production build โœ… Pass โ””โ”€ ๐ŸŽญ Playwright E2E tests โœ… Pass (then pushed to GH) โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ˜๏ธ GITHUB: Workflows kick off on GitHub machines when PR is created โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Create Pull Request โ†’ GitHub Actions triggered automatically โ”‚ โ”œโ”€ ๐Ÿค– Workflow 1: Lint & Type (biome, tsc) โ”‚ โ”œโ”€ Checkout code โ”‚ โ”œโ”€ Setup Node.js (from .nvmrc) โ”‚ โ”œโ”€ Install dependencies (npm ci) โ”‚ โ”œโ”€ Run Biome checks โœ… Pass โ”‚ โ””โ”€ Run TypeScript checks โœ… Pass โ”‚ โ”œโ”€ ๐Ÿค– Workflow 2: Unit Tests (vitest) โ”‚ โ”œโ”€ Checkout code โ”‚ โ”œโ”€ Setup Node.js (from .nvmrc) โ”‚ โ”œโ”€ Install dependencies (npm ci) โ”‚ โ””โ”€ Run Vitest tests โœ… Pass โ”‚ โ””โ”€ ๐Ÿค– Workflow 3: E2E Tests (playwright) โ”œโ”€ Checkout code โ”œโ”€ Setup Node.js (from .nvmrc) โ”œโ”€ Install dependencies (npm ci) โ”œโ”€ Install Playwright browsers โ”œโ”€ Build Next.js production โ””โ”€ Run Playwright tests โœ… Pass โ”€โ”€ Meanwhile, Vercel deploys Preview โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ๐Ÿš€ Vercel: Preview deployment ready โ”œโ”€ โœ… Vercel deployment status check (required to merge) โ””โ”€ Sends repository_dispatch event to GitHub โ””โ”€ ๐Ÿค– Workflow 4: E2E Tests (Vercel) โ”œโ”€ Triggered by Vercel (not PR event) โ”œโ”€ Runs Playwright against live Preview URL โ”œโ”€ Tests real Vercel deployment โœ… Pass โ””โ”€ Reports status back to PR commit GITHUB PR Status: โœ… All checks passed (push more commits to the PR and every workflow runs again) Okay I'm ready! [Merge Pull Request] โ† Click! ๐ŸŽ‰ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Ruleset Verified: "Protect main branch" โ”‚ โ”‚ โœ… All 5 required status checks passed โ”‚ โ”‚ โœ… Branch is up to date with main โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ main branch updated (merge commit preserves 3 commits) โ””โ”€ ๐Ÿš€ Vercel deployment triggered โ†’ Production โ””โ”€ ๐Ÿค– Workflow 4 again: E2E Tests (Vercel) โ”œโ”€ Runs Playwright against Production URL โœ… Pass โ””โ”€ Reports status to merge commit (can't block, already live) ``` Key CI Takeaways - Local Hooks โ€” Catch issues before commit or reaching GitHub - GitHub Actions โ€” Validate every PR with fresh environment (reproducible CI) - GitHub Ruleset โ€” Prevents merging broken code (all checks must pass) - Fast Feedback โ€” Pre-commit catches most issues locally - Quality Gates โ€” Code is validated 2ร— (local + CI) before reaching production