Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# CLAUDE.md

The project uses British English - strictly.

## Project Overview

A starter template repository — not a product. Clone it, add a UI component library, and build from there.

## Tech Stack

- **Framework**: Next.js 16 (App Router, React Compiler, TypeScript strict)
- **Styling**: Tailwind CSS v4
- **Testing**: Vitest + Testing Library (unit), Playwright (E2E)
- **Quality**: Biome (lint + format, replaces ESLint/Prettier), Lefthook (git hooks)
- **Deployment**: Vercel (Preview on PR, Production on merge)

## Breaking Changes (Next.js 16 / Tailwind 4)

- Tailwind v4: `@import "tailwindcss"` syntax (not `@tailwind` directives)
- Dynamic route `params` is a Promise - must await: `{ params }: { params: Promise<{ id: string }> }`
- Middleware renamed to Proxy: `proxy.ts` (not `middleware.ts`)
- `cacheComponents` enabled: uncached async data must be in `<Suspense>` or marked `"use cache"`
- `cacheComponents` enabled: route segment configs deprecated (`dynamic`, `revalidate`, `fetchCache`)

## Code Conventions

- Always use `@/` import aliases, even for siblings (`@/app/fonts` not `./fonts`)
- Only add `"use client"` when interactivity is needed
- Avoid manual `useMemo`/`useCallback` - React Compiler handles this
- Use `type` over `interface` for TypeScript definitions (enforced by Biome)

## Key Commands

```bash
# Quality Checks
npm run check # Lint + typecheck
npm run lint:md # Markdown linting

# Testing
npm run test # All tests (unit + e2e)
npm run test:unit # Vitest only
npm run test:e2e # Playwright only

# Vercel
vercel --help # All Vercel CLI commands
vercel list # Recent deployments
vercel env ls # Check env vars

# Utilities
fuser -k 3000/tcp 2>/dev/null; rm -f .next/dev/lock # Kill stuck dev server
```
69 changes: 69 additions & 0 deletions .claude/rules/components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
paths:
- "components/**/*.tsx"
- "app/**/*.tsx"
---

## UI Components Rules

**Build small, compose big, customise last.**

1. **Favour Composition over Monoliths**
- Create small, focused primitives → combine them flexibly.
- Avoid giant "mega-components" that do everything.

2. **Two-Layer Architecture**
- `components/ui/` — pure primitives (Button, Card, Input, Dialog…)
- `components/{feature}/` — feature compositions grouped by domain

Example structure (adapt to project needs):

```text
components/
├── ui/ # Layer 1: Primitives (pure, reusable)
│ ├── button.tsx
│ ├── dialog.tsx
│ └── input.tsx
├── auth/ # Layer 2: Feature compositions
│ ├── sign-in.tsx
│ └── sign-up.tsx
├── navigation/
│ ├── topbar.tsx
│ ├── sidebar.tsx
│ ├── mobile-nav.tsx
│ └── theme-toggle.tsx
├── search/
│ ├── search-input.tsx
│ └── search-results.tsx
└── tag-link.tsx # Cross-cutting single file → root OK
```

**Note:** If cross-cutting components grow to 2+ related files, create a folder or find a feature home.

3. **Composition-First APIs**
- Use slots / `asChild` (Radix/shadcn) or `as` (Catalyst) / children for flexibility.
- Prefer wrapping primitives over editing them. Only add variants to primitives when the pattern is reused across 2+ features. Avoid thin wrappers that just pass props with no added value — use `className` directly instead.

4. **Styling: Layout vs Visual**
- Utility classes for layout (margin, padding, flex, grid)
- Variants/props for visual styling (colours, borders, shadows)

5. **Variants & Compound Pattern**
- Variants via cva for styling flexibility.
- Compound components (e.g., `<Tabs> → <TabsList> + <TabsTrigger>`) for related parts.

6. **Keep Primitives "Dumb"**
- Low-level: presentation + a11y only.
- Never embed mock data (inject rather e.g. use `data/mock` instead)
- Higher-level: add logic / data (leverage Server Components).

7. **Customisation Hierarchy** (in order of preference)
1. `className` — one-off styling adjustments
2. Existing props/variants — use what's already exposed
3. New prop on primitive — only if genuinely reusable
4. New CVA variant — for new visual states across multiple uses
5. CSS variable override — last resort for deep customisation

**Note:** Props suit content/behaviour (e.g., `icon`, `loading`). Variants suit named visual states (e.g., `variant="destructive"`). Prefer simpler props before formal variants.

**One-Line Rule:** Small primitives + flexible composition = scalable, reusable UI without massive files.
29 changes: 29 additions & 0 deletions .claude/rules/tailwind.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
paths:
- "**/*.css"
- "app/**/*.tsx"
- "components/**/*.tsx"
---

# Tailwind 4.x Rules

1. **Centralised Theming** – `app/globals.css`
- Define all design tokens inside `@theme { … }`
- Use `@theme inline` when referencing CSS variables: `--color-primary: var(--primary)`
- Never hardcode hex/px/arbitrary values outside the theme

2. **Layer Order** (before imports)
- Declare `@layer base, components, utilities;` before `@import "tailwindcss"`
- Required for third-party CSS specificity control

3. **Utility-First**
- Prefer Tailwind classes directly in JSX
- Use `@apply` sparingly in globals.css for truly reusable patterns only

4. **Mobile-First**
- Base styles = mobile (no prefix)
- Enhance with `sm:`, `md:`, `lg:`, `xl:`, `2xl:`

5. **Colour Tokens**
- Use OKLCH format: `oklch(L C H)` — predictable lightness for dark mode
- Create foreground pairs: `--primary` + `--primary-foreground`
1 change: 1 addition & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"Bash(gh run list:*)",
"Bash(gh run view:*)",

"Bash(npm outdated)",
"Bash(npm run build)",
"Bash(npm run dev)",
"Bash(npm run start)",
Expand Down
21 changes: 12 additions & 9 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
{
// General editor settings
"editor.minimap.enabled": false,
"editor.wordWrap": "on",
"window.commandCenter": true,
"editor.colorDecorators": true,
"files.associations": { "*.css": "tailwindcss" }, // recommended by tailwind
"editor.quickSuggestions": { "strings": "on" }, // recommended by tailwind
"files.exclude": {
"**/.next": true, // Hide Next.js build output
"**/node_modules": true, // Hide npm installed dependencies
"next-env.d.ts": true, // Hide Next.js file (uneditable)
"tsconfig.tsbuildinfo": true // Hide TypeScript build info file
},

// Markdownlint: Markdown linting (matches CodeRabbit)
"[markdown]": {
Expand All @@ -18,11 +12,20 @@
}
},

// TAILWIND
"files.associations": { "*.css": "tailwindcss" }, // recommended by tailwind
"editor.quickSuggestions": { "strings": "on" }, // recommended by tailwind
"files.exclude": {
"**/.next": true, // Hide Next.js build output
"**/node_modules": true, // Hide npm installed dependencies
"next-env.d.ts": true, // Hide Next.js file (uneditable)
"tsconfig.tsbuildinfo": true // Hide TypeScript build info file
},
// Tailwind CSS IntelliSense
"tailwindCSS.experimental.configFile": "app/globals.css", // required
"tailwindCSS.validate": true, // linting

// Biome: formatting, linting, import organization
// Biome: formatting, linting, import organisation
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
Expand Down
50 changes: 0 additions & 50 deletions CLAUDE.md

This file was deleted.

14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ npm install # Install updated versions
| ▢ [.vscode/extensions.json](.vscode/extensions.json) | VS Code extension recommendations | Useful extensions to use in this Next.js project |
| ▢ [.vscode/settings.json](.vscode/settings.json) | VS Code editor and formatting settings | Enables auto-formatting and configures Biome and Tailwind extensions |
| 🌺 [.claude/commands/](.claude/commands) | Claude Code repeatable prompts | Write commits, evaluate CodeRabbit comments etc. |
| 🌺 [.claude/rules/](.claude/rules) | Claude Code context-aware rules | Auto-injected when editing matching file paths |
| 🌺 [.claude/settings.json](.claude/settings.json) | Claude Code permissions | Allow/Deny permissions for files, commands, websearch etc |
| 🌺 [.mcp.json](.mcp.json) | Claude Code MCP config | e.g. Playwright MCP so Claude Code can "see" app and adjust |
| 🌺 [CLAUDE.md](CLAUDE.md) | Claude Code project context | Documents tech stack for Claude Code (customise!) |
| 🌺 [.claude/CLAUDE.md](.claude/CLAUDE.md) | Claude Code project context | Documents tech stack for Claude Code (customise!) |
| 🅽 [next.config.ts](next.config.ts) | Next.js framework configuration | Enables React Compiler and customises Next.js build settings |
| 🅽 [package.json](package.json) | Project dependencies and npm scripts | Defines project dependencies, scripts, and npm package metadata |
| 🅽 [postcss.config.mjs](postcss.config.mjs) | PostCSS plugins config for CSS processing | Enables Tailwind CSS v4 processing via PostCSS plugin |
Expand Down Expand Up @@ -231,3 +232,14 @@ Key CI Takeaways
(3) GitHub - A branch protection ruleset to be setup to protect main. Incldues checks for GitHub workflow jobs to pass before merging PR to main. See [x_docs/project-setup.md](x_docs/project-setup.md).

(4) Vercel For Deploys - When you raise a PR it automatically deploys to Vercel Preview and Playwright e2e tests run on that too in addition to GitHub servers. When you merge the PR into main, you are deploying to Vercel prod. See [x_docs/project-setup.md](x_docs/project-setup.md).

## Common Additions for New Projects

When starting a new project from this template, you'll typically add:

- UI components (shadcn/ui, Radix, Tailwind UI kit, or Headless UI)
- State management (Zustand, Jotai, or React Context)
- Data fetching (React Query, SWR, or native fetch with Server Components)
- Forms (React Hook Form, Zod for validation)
- Authentication (NextAuth.js, Clerk, or Supabase Auth)
- Database/ORM (Neon or Supabase with Prisma or Drizzle. Or try Convex!)
8 changes: 8 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
"enabled": true,
"rules": {
"recommended": true,
"style": {
"useConsistentTypeDefinitions": {
"level": "error",
"options": {
"style": "type"
}
}
},
"suspicious": {
"noUnknownAtRules": "off"
}
Expand Down
8 changes: 8 additions & 0 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ import type { NextConfig } from "next";
const nextConfig: NextConfig = {
reactCompiler: true,

// TypeScript validates <Link href> and router.push() against actual routes
typedRoutes: true,

// Position dev indicator (default is bottom-left)
devIndicators: {
position: "bottom-right",
},

// Enables "use cache" directive, cacheLife(), cacheTag(), and Partial Prerendering.
// Routes are dynamic by default; use "use cache" to opt into caching.
cacheComponents: true,
Expand Down
Loading
Loading