or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

api.mdconcepts.mdindex.mdpages-router.mdpatterns.mdspecial-files.md
tile.json

tessl/npm-next

The React Framework for production-grade applications with server-side rendering, static site generation, and full-stack capabilities

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/next@16.0.x

To install, run

npx @tessl/cli install tessl/npm-next@16.0.0

index.mddocs/

Next.js - Quick Reference

Next.js 16.0.0 - React framework for production with App Router (recommended) and Pages Router (legacy).

Installation & Setup

npm install next@16.0.0 react@19.0.0 react-dom@19.0.0

File Structure:

app/
├── layout.tsx       # Root layout (wraps all pages)
├── page.tsx         # Home page route: /
├── loading.tsx      # Loading UI fallback
├── error.tsx        # Error boundary
├── not-found.tsx    # 404 page
└── blog/
    ├── page.tsx     # Blog index route: /blog
    └── [slug]/
        └── page.tsx # Dynamic route: /blog/[slug]

Quick Start

Server Component (Default)

// app/page.tsx
export default async function Page() {
  const data = await fetch('https://api.example.com', {
    next: { revalidate: 60 } // Cache for 60s
  });
  return <div>{await data.json()}</div>;
}

Client Component

// app/counter.tsx
'use client';
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

Decision Tree: Which Approach?

App Router vs Pages Router?

  • New project? → App Router ⚡ (better performance, modern features)
  • Existing Pages app? → Continue with Pages or migrate gradually

Server vs Client Component?

  • Fetching data, accessing backend? → Server Component ⚡ (smaller bundle, faster)
  • Needs interactivity (useState, onClick)? → Client Component 🔄 (required for interactivity)

Static vs Dynamic?

  • Content doesn't change often? → Static with ISR ⚡ (fastest, cached at edge)
  • User-specific or real-time? → Dynamic ⚠️ (fresh data, slower)

Core Patterns

1. Navigation (Client)

'use client';
import { useRouter } from 'next/navigation';
import Link from 'next/link';

const router = useRouter();
router.push('/about');

<Link href="/about">About</Link>

2. Redirect (Server)

import { redirect } from 'next/navigation';

export default async function Page() {
  const user = await getUser();
  if (!user) redirect('/login');
  return <div>{user.name}</div>;
}

3. Data Fetching with Caching

// ⚡ Time-based revalidation (ISR) - Best for predictable content
const res = await fetch('https://api.example.com', {
  next: { revalidate: 3600 } // 1 hour
});

// ⚡ Tag-based revalidation - Best for on-demand updates
const posts = await fetch('https://api.example.com/posts', {
  next: { tags: ['posts'] }
});
revalidateTag('posts'); // Later in Server Action

// ⚠️ Force fresh data - Slower, always hits server
const res = await fetch('https://api.example.com', {
  cache: 'no-store'
});

4. Dynamic Routes

// app/blog/[slug]/page.tsx
export default async function Post({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const post = await getPost(slug);
  return <article>{post.title}</article>;
}

5. API Routes

// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  return NextResponse.json({ users: [] });
}

export async function POST(request: NextRequest) {
  const body = await request.json();
  return NextResponse.json(body, { status: 201 });
}

6. Server Actions

// app/actions.ts
'use server';

export async function createPost(formData: FormData) {
  const title = formData.get('title');
  await savePost(title);
  revalidatePath('/posts');
}

// app/form.tsx
import { createPost } from './actions';

export default function Form() {
  return (
    <form action={createPost}>
      <input name="title" />
      <button type="submit">Submit</button>
    </form>
  );
}

Core Imports

// Navigation
import { useRouter, usePathname, useSearchParams } from 'next/navigation';
import Link from 'next/link';
import { redirect, notFound } from 'next/navigation';

// Components
import Image from 'next/image';
import Script from 'next/script';

// Server
import { NextRequest, NextResponse } from 'next/server';
import { revalidatePath, revalidateTag } from 'next/cache';
import { headers, cookies } from 'next/headers';

// Fonts
import { Inter } from 'next/font/google';
import localFont from 'next/font/local';

Image Optimization

import Image from 'next/image';

<Image
  src="/photo.jpg"
  alt="Photo"
  width={800}
  height={600}
  priority // For above-the-fold
  placeholder="blur"
/>

CLI Commands

next dev --turbo -p 4000    # Dev server with Turbopack on port 4000
next dev -H 0.0.0.0         # Dev server accessible on network
next build --profile        # Production build with React profiling
next build --no-lint        # Build without linting
next start -p 8080          # Start production server on port 8080
next lint --fix             # Run and auto-fix linting errors
next info                   # Display system information

Configuration

// next.config.js
const nextConfig = {
  reactStrictMode: true,
  images: {
    domains: ['example.com'],
  },
};

module.exports = nextConfig;

Route Segment Config

export const revalidate = 60; // ISR: revalidate every 60s
export const dynamic = 'force-dynamic'; // Always SSR
export const runtime = 'nodejs' | 'edge';

Performance Patterns

⚡ Static Generation (ISR) - Fastest

export const revalidate = 3600; // Revalidate every hour

export default async function Page() {
  const data = await fetch('https://api.example.com');
  return <div>{data}</div>;
}

🔄 Streaming with Suspense - Progressive Loading

import { Suspense } from 'react';

export default function Page() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <SlowComponent />
    </Suspense>
  );
}

Common Solutions

Authentication

import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

export default async function Dashboard() {
  const cookieStore = await cookies();
  if (!cookieStore.get('token')) redirect('/login');
  return <div>Dashboard</div>;
}

Loading & Error States

// app/loading.tsx
export default function Loading() {
  return <div>Loading...</div>;
}

// app/error.tsx
'use client';
export default function Error({
  error,
  reset
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <div>
      <h2>{error.message}</h2>
      <button onClick={reset}>Try again</button>
    </div>
  );
}

Common Mistakes to Avoid

Server vs Client Components:

  • ❌ Adding 'use client' to all components (use sparingly, only when needed)
  • ❌ Using React hooks in Server Components (useState, useEffect not available)
  • ✓ Keep components as Server Components by default for better performance

Data Fetching:

  • ❌ Fetching data in Client Components when Server Components can do it
  • ❌ Using useEffect for initial data loads (use Server Components instead)
  • ✓ Fetch in Server Components, pass data as props to Client Components

Async Params (Next.js 15+):

  • const { id } = params; (params is now a Promise)
  • const { id } = await params; (must await in Next.js 15+)
  • const { q } = searchParams; (searchParams is also a Promise)
  • const { q } = await searchParams; (must await)

Image Optimization:

  • ❌ Using <img> tags (missing optimization)
  • ❌ Not configuring external domains in next.config.js
  • ✓ Use <Image> component and configure images.domains

Caching Issues:

  • ❌ Forgetting to revalidate after mutations
  • ❌ Using cache: 'no-store' everywhere (loses performance benefits)
  • ✓ Use appropriate revalidation strategy (time-based or tag-based)

Route Handlers:

  • ❌ Returning multiple responses in same handler
  • ❌ Not handling errors properly (causes "Headers already sent")
  • ✓ Return single NextResponse per request, add try-catch blocks

Troubleshooting Quick Fixes

"Error: Headers already sent"

  • Cause: Multiple responses sent in API route or middleware
  • Fix: Ensure only one return NextResponse per code path, check for missing return statements

Hydration Mismatch

  • Cause: Server-rendered HTML differs from client render
  • Common: Using Date.now(), Math.random(), browser-only APIs in Server Components
  • Fix: Move dynamic values to Client Components or use suppressHydrationWarning

"Module not found" or Build Errors

  • Fix: Delete .next folder and node_modules, run npm install, restart dev server
rm -rf .next node_modules
npm install
next dev

Image Optimization Failed

  • Cause: External domain not configured
  • Fix: Add domain to next.config.js:
images: {
  domains: ['example.com', 'cdn.example.com'],
}

Middleware Not Running

  • Cause: Incorrect matcher pattern or file location
  • Fix: Ensure middleware.ts is at project root (not in app/), check matcher config
export const config = {
  matcher: ['/dashboard/:path*', '/((?!api|_next/static|_next/image|favicon.ico).*)'],
};

Fetch Caching Issues

  • Cause: Next.js caches fetch by default
  • Fix: Use cache: 'no-store' for dynamic data or set revalidation time
fetch(url, { cache: 'no-store' }) // Always fresh
fetch(url, { next: { revalidate: 60 } }) // Cache for 60s

TypeScript Errors with Params

  • Cause: Next.js 15+ made params async
  • Fix: Update function signature and await params:
export default async function Page({
  params
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params;
}

File Organization Best Practices

Recommended Project Structure:

app/
├── (auth)/              # Route group (not in URL)
│   ├── login/
│   │   └── page.tsx     # /login
│   └── register/
│       └── page.tsx     # /register
├── (dashboard)/         # Route group
│   ├── layout.tsx       # Shared dashboard layout
│   ├── page.tsx         # /dashboard
│   └── settings/
│       └── page.tsx     # /dashboard/settings
├── api/
│   └── users/
│       ├── route.ts     # GET/POST /api/users
│       └── [id]/
│           └── route.ts # GET/PATCH/DELETE /api/users/[id]
├── components/          # Shared React components
│   ├── ui/              # UI primitives
│   └── features/        # Feature-specific components
├── actions/             # Server Actions
│   ├── auth.ts
│   └── posts.ts
├── lib/                 # Utilities and helpers
│   ├── db.ts
│   └── utils.ts
├── layout.tsx           # Root layout
└── page.tsx             # Home page

middleware.ts            # Root-level middleware
next.config.js          # Next.js configuration

Key Principles:

  • Use route groups (name) to organize without affecting URLs
  • Colocate components, actions, and utilities with features when possible
  • Keep shared code in top-level directories (components/, lib/)
  • Use Server Actions in actions/ directory for mutations

Navigation Guide for Agents

80% of queries: Start with this file → Quick answers to common patterns

Architectural decisions: See concepts.md for when-to-use guidance

Complete implementations: See patterns.md for production-ready examples

Detailed API reference: See api.md for exhaustive interface definitions

Special files reference: See special-files.md for layout.tsx, page.tsx, etc.

Legacy Pages Router: See pages-router.md - use only for existing apps

Progressive Loading Strategy:

  1. Check this file first (includes CLI commands, common mistakes, troubleshooting)
  2. Consult concepts.md for architectural decisions
  3. Use patterns.md for complete implementations
  4. Reference api.md only for edge cases and complete type definitions

Query Routing

"How do I implement [X]?"patterns.md "Should I use [X] or [Y]?"concepts.md "What props does [component] accept?"api.md "Show me a [pattern] example"patterns.md "Why is [X] not working?" → Check "Troubleshooting Quick Fixes" above "Am I making a mistake with [Y]?" → Check "Common Mistakes to Avoid" above