Our review
Generates production-ready Next.js code by automatically detecting the project's configuration (App Router, TypeScript, Tailwind, etc.).
Strengths
- Auto-detection of router type, source directory, and styling tools.
- Templates for server components, API routes, layouts, loading, and error boundaries.
- Respects existing project conventions.
Limitations
- Only covers standard Next.js patterns, not advanced custom setups.
- Depends on accurate project detection (may fail with unusual folder structures).
Use this skill when you need to quickly generate a new page, API route, layout, or other Next.js file while adhering to project conventions.
Avoid this skill if you need to generate code for a non-Next.js framework, or if you require highly specific customizations not covered by the templates.
Security analysis
SafeThe skill uses only safe detection commands (checking directories, grepping package.json) and generates boilerplate code. No exfiltration, destruction, or obfuscation. Allowed tools (Read, Write, Bash) are used in a controlled manner.
No concerns found
Examples
Create a new page for blog posts in the app router with metadata and a server component that fetches posts.Add an API route for users with GET and POST handlers, including error handling.Scaffold a layout for the dashboard section with a sidebar navigation and content area.name: nextjs-scaffold description: Generate Next.js pages, API routes, server components, layouts, and middleware following project conventions. Use when user says "create page", "new route", "scaffold", "generate component", "add api endpoint", "create layout", or needs any Next.js boilerplate generated. allowed-tools: Read, Write, Edit, Glob, Grep, Bash
Next.js Scaffolding
Generate production-ready Next.js code following the project's existing patterns. Auto-detects App Router vs Pages Router, TypeScript config, and styling approach.
Detection workflow
Before generating anything, detect the project's setup:
# 1. Router type
if [ -d "app" ] || [ -d "src/app" ]; then
echo "APP_ROUTER"
elif [ -d "pages" ] || [ -d "src/pages" ]; then
echo "PAGES_ROUTER"
fi
# 2. Source directory
if [ -d "src" ]; then
echo "SRC_DIR=src"
else
echo "SRC_DIR=."
fi
# 3. TypeScript
if [ -f "tsconfig.json" ]; then
echo "TYPESCRIPT=true"
fi
# 4. Styling
if [ -f "tailwind.config.js" ] || [ -f "tailwind.config.ts" ]; then
echo "TAILWIND=true"
fi
if ls src/**/*.module.css 2>/dev/null | head -1; then
echo "CSS_MODULES=true"
fi
# 5. Database
grep -l "supabase" package.json 2>/dev/null && echo "SUPABASE=true"
grep -l "firebase" package.json 2>/dev/null && echo "FIREBASE=true"
grep -l "prisma" package.json 2>/dev/null && echo "PRISMA=true"
# 6. Auth
grep -l "next-auth\|@auth" package.json 2>/dev/null && echo "NEXTAUTH=true"
grep -l "@supabase/auth" package.json 2>/dev/null && echo "SUPABASE_AUTH=true"
App Router templates
Page (Server Component)
// app/{route}/page.tsx
import { Metadata } from 'next'
export const metadata: Metadata = {
title: '{Page Title}',
description: '{Page description}',
}
export default async function {PageName}Page() {
// Fetch data server-side
return (
<main className="container mx-auto px-4 py-8">
<h1 className="text-3xl font-bold">{Page Title}</h1>
</main>
)
}
Page with params
// app/{route}/[id]/page.tsx
interface Props {
params: Promise<{ id: string }>
}
export default async function {Name}Page({ params }: Props) {
const { id } = await params
return (
<main className="container mx-auto px-4 py-8">
<h1>{id}</h1>
</main>
)
}
Layout
// app/{route}/layout.tsx
export default function {Name}Layout({
children,
}: {
children: React.ReactNode
}) {
return (
<div>
{children}
</div>
)
}
Loading state
// app/{route}/loading.tsx
export default function Loading() {
return (
<div className="flex items-center justify-center min-h-[50vh]">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900" />
</div>
)
}
Error boundary
// app/{route}/error.tsx
'use client'
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<div className="flex flex-col items-center justify-center min-h-[50vh] gap-4">
<h2 className="text-xl font-semibold">Something went wrong</h2>
<button
onClick={reset}
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
>
Try again
</button>
</div>
)
}
API Route (App Router)
// app/api/{name}/route.ts
import { NextRequest, NextResponse } from 'next/server'
export async function GET(request: NextRequest) {
try {
// Implementation
return NextResponse.json({ data: [] })
} catch (error) {
console.error('[API] {name} GET error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json()
// Validate input
// Implementation
return NextResponse.json({ success: true }, { status: 201 })
} catch (error) {
console.error('[API] {name} POST error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}
Server Action
// app/{route}/actions.ts
'use server'
import { revalidatePath } from 'next/cache'
export async function create{Name}(formData: FormData) {
const field = formData.get('field') as string
if (!field) {
return { error: 'Field is required' }
}
try {
// Database operation
revalidatePath('/{route}')
return { success: true }
} catch (error) {
return { error: 'Failed to create' }
}
}
Middleware
// middleware.ts (project root)
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Auth check example
const token = request.cookies.get('auth-token')?.value
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
export const config = {
matcher: ['/dashboard/:path*', '/api/:path*'],
}
Supabase integration patterns
Server-side client
// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
export async function createClient() {
const cookieStore = await cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() { return cookieStore.getAll() },
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options))
},
},
}
)
}
Client-side client
// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr'
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
Scaffold workflow
- Detect project setup (router, TS, styling, DB)
- Read existing similar files to match patterns
- Generate using the matching template
- Verify the file compiles:
npx tsc --noEmit {file} - Report what was created and where
Scope constraints
- Always detect the project setup BEFORE generating code
- Match existing patterns (if the project uses
src/, put files there) - Never overwrite existing files without confirmation
- Never generate Pages Router code for App Router projects or vice versa
- Always include error handling in API routes
- Always include TypeScript types when the project uses TS
Next.js App Router Expert
Development
A skill that turns Claude into a Next.js App Router expert.
README Generator
Development
Creates professional and comprehensive README.md files for your projects.
API Documentation Writer
Development
Generates comprehensive API documentation in OpenAPI/Swagger format.