This repository is a high-performance Next.js 16 dev blog using the App Router, Fumadocs MDX, Tailwind CSS 4, Drizzle ORM, Neon Postgres, Clerk, and React 19 and TypeScript.
- Package manager:
pnpmonly. - Framework: Next.js 16 App Router with Turbopack for development.
- React: 19.
- Styling: Tailwind CSS 4 through CSS/PostCSS. Do not add
tailwind.config.jsunless the project is intentionally migrated to config-based Tailwind. - Content: Fumadocs MDX in
blog/content/. - Database: Neon Postgres through Drizzle ORM.
- Auth: Clerk, with the existing no-op fallback in
middleware.ts. - Icons:
lucide-reactonly.
app/: App Router routes, layouts, metadata, RSS, sitemap, and API routes.components/: Shared UI components. Keep interactive leaf components client-side.lib/: Shared application code.lib/db/schema.ts: Drizzle schema.lib/db/client.ts: Database client factory andgetDb().lib/hooks/: Client hooks and TanStack Query hooks.lib/generated/read-times.json: Generated read-time data. Do not edit by hand.blog/content/: MDX article source files.drizzle/: Generated Drizzle migrations..source/: Fumadocs-generated output. Do not edit by hand.scripts/: Project automation, including read-time generation.types/: Shared TypeScript types.
Do not create a src/ directory. Internal imports must use the root alias @/.
- Prefer Server Components. Add
'use client'only for browser interactivity, React client hooks, TanStack Query hooks, or client-only libraries. - Await asynchronous Next.js 16 request APIs before reading values. Treat
params,searchParams,cookies(), and similar dynamic APIs as async when used in App Router code. - Keep the Clerk fallback resilient. Do not break startup when Clerk environment variables are missing; preserve the
isClerkConfigured()gate inmiddleware.ts. - After editing
lib/db/schema.ts, runpnpm run db:generate. - Use Drizzle types from schema objects, such as
InferSelectModelandInferInsertModel, instead of hand-written row types. - After adding, deleting, renaming, or editing any file in
blog/content/, runpnpm run readtime. - Do not manually edit generated files in
lib/generated/,.source/, ordrizzle/unless the task explicitly requires generated output review or repair. - New code must pass TypeScript strict mode. Avoid
anyunless there is a narrow, documented reason. - Favor existing utilities in
lib/and existing components before adding dependencies or new abstractions. - Route-specific components should live near the route when they are not reused elsewhere.
| Task | Command |
|---|---|
| Development | pnpm run dev |
| Production build | pnpm run build |
| Lint | pnpm run lint |
| Format | pnpm run format |
| Format check | pnpm run format:check |
| Generate read times | pnpm run readtime |
| Generate Drizzle migration | pnpm run db:generate |
| Apply Drizzle migrations | pnpm run db:migrate |
| Push schema to database | pnpm run db:push |
| Open Drizzle Studio | pnpm run db:studio |
pnpm run dev and pnpm run build already run readtime and fumadocs-mdx before starting Next.js.
- Use
@/for internal imports. - Keep Server Component data access on the server.
- Keep browser-only code out of Server Components.
- Use
server-onlyfor modules that must never be imported by Client Components when appropriate. - Use structured validation with existing schemas/utilities where available.
- Keep edits scoped to the requested change and nearby affected code.