FRMWRK
Next.js Boilerplate
Build tools with AI

What's included

Every technology in the default stack, why it's here, and how to use it.

Next.js + TypeScript

16.2.6

Full-stack React framework with file-based routing, server components, and built-in API routes.

Why we use it

Single framework for both frontend and backend. Server components reduce client bundle size. API routes live alongside pages.

// app/api/hello/route.ts
export async function GET() {
  return Response.json({ message: 'Hello world' })
}

// app/dashboard/page.tsx
export default async function Dashboard() {
  const data = await fetch('/api/data')  // server-side
  return <main>{/* ... */}</main>
}

Tailwind CSS v4 + shadcn/ui

Tailwind 4 · base-nova style

Utility-first CSS with a full design system. Components are built on Base UI primitives for accessibility.

Why we use it

CSS variables for theming (dark/light mode included). No runtime overhead. shadcn/ui components are copy-owned — no lock-in.

// components/ui/button.tsx is copy-owned — edit freely
import { Button } from '@/components/ui/button'

<Button variant="outline" size="sm">Click me</Button>
<Button variant="destructive">Delete</Button>

// Tailwind utilities work everywhere
<div className="bg-card border border-border rounded-lg p-4">
  <p className="text-muted-foreground text-sm">Card content</p>
</div>

Zod

4.4.3

TypeScript-first schema declaration and validation. Used at every API boundary and for external data.

Why we use it

Validates and types data at the same time. One schema → TypeScript type + runtime validation. Required by AGENTS.md security rules.

import { z } from 'zod'

const CreateUserSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  role: z.enum(['admin', 'editor', 'viewer']),
})

// In an API route:
export async function POST(req: Request) {
  const body = await req.json()
  const parsed = CreateUserSchema.safeParse(body)
  if (!parsed.success) return Response.json({ error: parsed.error }, { status: 400 })
  // parsed.data is fully typed ✓
}

ESLint + Prettier

ESLint 9 · Prettier 3

ESLint enforces code quality and Next.js best practices. Prettier ensures consistent formatting.

Why we use it

Catches common mistakes early. Format-on-save in Cursor/VS Code. Tailwind class order is auto-sorted by prettier-plugin-tailwindcss.

# Run both before every commit:
npm run check    # tsc --noEmit && eslint

# Or run separately:
npm run typecheck   # TypeScript only
npm run lint        # ESLint only
npm run format      # Prettier (auto-fix)

Vitest

4.1.8

Fast unit test runner with native TypeScript support and Jest-compatible API.

Why we use it

Uses the same Vite config as the project — no separate bundler setup. Instant hot reloading in watch mode. Jest drop-in replacement.

// app/__tests__/health.test.ts
import { expect, test } from 'vitest'

test('health endpoint returns ok', async () => {
  const res = await fetch('http://localhost:3000/api/health')
  const json = await res.json()
  expect(json.status).toBe('ok')
})

# Run tests:
npm run test          # run once
npx vitest --watch    # watch mode