All TypeScript templates

Next.js + Tailwind + Prisma Stack

Full-stack Next.js with Prisma ORM, Tailwind CSS, and Postgres.

DevZone Tools1,850 copiesUpdated Mar 12, 2026Next.jsTailwindPrismaTypeScript
# CLAUDE.md — Next.js + Tailwind + Prisma

## Project layout

- `app/` — routes
- `components/` — shared components (server-first)
- `lib/db.ts` — singleton Prisma client (see below)
- `lib/actions/<feature>.ts` — Server Actions
- `prisma/schema.prisma` — single source of truth for the data model

## Prisma client

- Export a singleton from `lib/db.ts` to avoid exhausting connection pools in dev:
  ```ts
  import { PrismaClient } from '@prisma/client'
  const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient }
  export const db = globalForPrisma.prisma ?? new PrismaClient()
  if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db
  ```
- Never instantiate `new PrismaClient()` outside this file.
- Run `prisma generate` on every schema change. Add it to `postinstall`.

## Data access

- Query Prisma in Server Components and Server Actions only. Don't pass the Prisma client to the client.
- Use `select` to project only the fields you need. Don't return entire rows by default.
- Wrap multi-step writes in `prisma.$transaction`. If a write fails halfway, the rollback must be automatic.
- For pagination, use cursor-based pagination (`cursor`, `take`) — not `skip` + `take`.

## Migrations

- `prisma migrate dev --name <change>` for local schema changes; `prisma migrate deploy` in CI.
- Never edit a migration file after merging. Generate a new migration to fix forward.
- Seed data lives in `prisma/seed.ts`, runnable via `prisma db seed`.

## Tailwind

- Use semantic spacing scale (`p-4`, `gap-3`) — no magic pixel values via `[12px]` unless absolutely required.
- Component variants: use `cva` from `class-variance-authority`, not nested ternaries inside `className`.
- Mobile-first: write base styles, then `sm:`, `md:`, `lg:`. Don't write `lg:` styles before base.

## Environment

- `DATABASE_URL` and `DIRECT_URL` (for migrations) live in `.env`. Never commit `.env`.
- For pooled connections (Vercel, etc.), set `DATABASE_URL` to the pooled URL and `DIRECT_URL` to the direct one in `prisma/schema.prisma`.

## Don't

- Don't query Prisma from a Client Component or `useEffect`. Move it to the server.
- Don't use `findFirst` when `findUnique` would do — uniqueness is a hint to the planner.
- Don't disable type generation to ship.
- Don't leak full DB error messages to the client.

Other TypeScript templates