active
TypeScript Next.js Rules
Safe
System VerifiedSafe
Context rules for AI agents working in TypeScript/Next.js App Router projects. Covers strict typing, server vs client components, Tailwind, Zod, and file conventions.
@api/typescript-next-js-rules
typescript
nextjs
react
rules
context
tailwind
TypeScript Next.js Rules
Context skill: Install this into your agent to enforce consistent, production-quality patterns in TypeScript Next.js App Router projects. Works with Claude Code, Cursor, Windsurf, and any agent that reads context files.
Stack Assumptions
- Next.js 14+ with App Router (not Pages Router)
- TypeScript with strict mode enabled (
"strict": truein tsconfig) - Tailwind CSS for styling
- Zod for runtime validation
- Supabase or Prisma for database (adapt as needed)
File & Directory Conventions
code
app/
(group)/ ← Route groups (no URL segment)
layout.tsx ← Shared layout
page.tsx ← Route page (server component by default)
loading.tsx ← Suspense fallback
error.tsx ← Error boundary ('use client' required)
api/
route.ts ← API routes (GET, POST, etc. as named exports)
components/
ui/ ← Primitive UI: Button, Card, Badge, etc.
feature/ ← Feature-specific composed components
lib/
utils/ ← Pure utility functions (no React)
types/ ← TypeScript type definitions
actions/ ← Server Actions
hooks/ ← Custom React hooks (client-side)
Server vs Client Components
Default to Server Components. Only add 'use client' when you need:
useStateoruseReduceruseEffector lifecycle hooks- Browser APIs (
window,localStorage, etc.) - Event handlers that run in the browser
- Third-party client-only libraries
Never put 'use client' at the top of a layout file.
TypeScript Rules
typescript
// ✅ Always type function return values explicitly
async function getUser(id: string): Promise<User | null> { ... }
// ✅ Use `type` for unions/intersections, `interface` for object shapes
type Status = 'pending' | 'active' | 'archived'
interface UserProfile { id: string; email: string; }
// ✅ Never use `any` — use `unknown` and narrow
function parse(input: unknown): string {
if (typeof input !== 'string') throw new Error('Expected string')
return input
}
// ❌ Never
const data: any = response.json()
// ✅ Type API responses with Zod
const UserSchema = z.object({ id: z.string().uuid(), email: z.string().email() })
type User = z.infer<typeof UserSchema>
API Routes
typescript
// app/api/users/route.ts
import { NextResponse } from 'next/server'
import { z } from 'zod'
const CreateUserSchema = z.object({
email: z.string().email(),
name: z.string().min(1).max(100),
})
export async function POST(request: Request) {
const body = await request.json()
const result = CreateUserSchema.safeParse(body)
if (!result.success) {
return NextResponse.json({ error: result.error.flatten() }, { status: 422 })
}
// ... proceed with result.data (fully typed)
}
Data Fetching
typescript
// ✅ Server Component data fetching — no useEffect
export default async function UsersPage() {
const users = await getUsers() // Direct async call in component
return <UserList users={users} />
}
// ✅ Parallel fetching with Promise.all
const [user, posts] = await Promise.all([getUser(id), getPosts(id)])
// ✅ Use `cache` for request deduplication
import { cache } from 'react'
const getUser = cache(async (id: string) => { ... })
Error Handling
typescript
// ✅ Never throw in Server Components — use error.tsx
// app/(main)/error.tsx
'use client'
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
return <div><h2>Something went wrong</h2><button onClick={reset}>Try again</button></div>
}
// ✅ API routes always return typed error shapes
return NextResponse.json({ error: 'Not found', code: 'USER_NOT_FOUND' }, { status: 404 })
Tailwind CSS
- Use Tailwind utility classes directly — no custom CSS unless absolutely necessary
- Use
cn()helper (fromclsx+tailwind-merge) to conditionally join classes - Dark mode via
dark:variants (not separate stylesheets) - Never use inline
style={{}}for values that Tailwind covers - Use
@applysparingly — only in component-level.module.cssfiles if needed
Do Not
- Do not use
pages/directory — App Router only - Do not import server-only code into client components (will cause runtime errors)
- Do not use
getServerSidePropsorgetStaticProps— use async Server Components - Do not
console.login production code — use a proper logger - Do not hardcode environment variables — use
process.env.VARwith validation on startup - Do not use default exports for utility functions — named exports only
Dormant$0/mo
$20 more to next tier
Created by
Info
Created February 20, 2026
Version 1.0.0
Context
Terminal output
Embed
Add this skill card to any webpage.
<iframe src="https://skillslap.com/skill/8068b095-f3ea-4180-91ce-b3ff7767f61e/embed"
width="400" height="200"
style="border:none;border-radius:12px;"
title="SkillSlap Skill: TypeScript Next.js Rules">
</iframe>