)
}
```
**See Reference**: `references/react-19-integration.md`
---
## Turbopack (Stable in Next.js 16)
**NEW**: Turbopack is now the **default bundler** in Next.js 16.
**Performance Improvements**:
- 2–5× faster production builds
- Up to 10× faster Fast Refresh
**Opt-out** (if needed):
```bash
npm run build -- --webpack
```
**Enable File System Caching** (experimental):
```typescript
// next.config.ts
import type { NextConfig } from 'next'
const config: NextConfig = {
experimental: {
turbopack: {
fileSystemCaching: true, // Beta: Persist cache between runs
},
},
}
export default config
```
---
### Turbopack Production Limitations (as of Next.js 16.1)
**Known Issues**:
#### 1. Prisma Incompatibility
**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721)
Turbopack production builds fail with Prisma ORM (v6.5.0+). Error: "The 'path' argument must be of type string."
**Workaround**:
```bash
# Use webpack for production builds
npm run build -- --webpack
```
Or in `next.config.ts`:
```typescript
const config: NextConfig = {
experimental: {
turbo: false, // Disable Turbopack for production
},
};
```
---
#### 2. Source Maps Security Risk
**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721)
Turbopack currently **always builds production source maps for the browser**, exposing source code in production deployments.
**Workaround**:
```typescript
// next.config.ts
const config: NextConfig = {
productionBrowserSourceMaps: false, // Disable source maps
};
```
Or exclude `.map` files in deployment:
```bash
# .vercelignore or similar
*.map
```
---
#### 3. External Module Hash Mismatches (Monorepos)
**Source**: [GitHub Issue #87737](https://github.com/vercel/next.js/issues/87737)
Turbopack generates external module references with hashes that don't match when `node_modules` structure differs (pnpm, yarn workspaces, monorepos). This causes "Module not found" errors in production builds.
**Symptoms**:
- Build succeeds locally but fails in CI/CD
- Hash mismatches between bundled references and actual module files
**Workaround**:
```typescript
// next.config.ts
const config: NextConfig = {
experimental: {
serverExternalPackages: ['package-name'], // Explicitly externalize packages
},
};
```
---
#### 4. Bundle Size Differences (Community-sourced)
**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721)
Bundle sizes built with Turbopack may differ from webpack builds. This is expected and being optimized as Turbopack matures.
---
## Common Errors & Solutions
### 1. Error: `params` is a Promise
**Error**:
```
Type 'Promise<{ id: string }>' is not assignable to type '{ id: string }'
```
**Cause**: Next.js 16 changed `params` to async.
**Solution**: Await `params`:
```typescript
// ❌ Before
export default function Page({ params }: { params: { id: string } }) {
const id = params.id
}
// ✅ After
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
}
```
---
### 2. Error: `searchParams` is a Promise
**Error**:
```
Property 'query' does not exist on type 'Promise<{ query: string }>'
```
**Cause**: `searchParams` is now async in Next.js 16.
**Solution**:
```typescript
// ❌ Before
export default function Page({ searchParams }: { searchParams: { query: string } }) {
const query = searchParams.query
}
// ✅ After
export default async function Page({ searchParams }: { searchParams: Promise<{ query: string }> }) {
const { query } = await searchParams
}
```
---
### 3. Error: `cookies()` requires await
**Error**:
```
'cookies' implicitly has return type 'any'
```
**Cause**: `cookies()` is now async in Next.js 16.
**Solution**:
```typescript
// ❌ Before
import { cookies } from 'next/headers'
export function MyComponent() {
const cookieStore = cookies()
}
// ✅ After
import { cookies } from 'next/headers'
export async function MyComponent() {
const cookieStore = await cookies()
}
```
---
### 4. Error: Parallel route missing `default.js`
**Error**:
```
Error: Parallel route @modal/login was matched but no default.js was found
```
**Cause**: Next.js 16 requires `default.js` for all parallel routes.
**Solution**: Add `default.tsx` files:
```typescript
// app/@modal/default.tsx
export default function ModalDefault() {
return null
}
```
---
### 5. Error: `revalidateTag()` requires 2 arguments
**Error**:
```
Expected 2 arguments, but got 1
```
**Cause**: `revalidateTag()` now requires a `cacheLife` argument in Next.js 16.
**Solution**:
```typescript
// ❌ Before
revalidateTag('posts')
// ✅ After
revalidateTag('posts', 'max')
```
---
### 6. Error: Cannot use React hooks in Server Component
**Error**:
```
You're importing a component that needs useState. It only works in a Client Component
```
**Cause**: Using React hooks in Server Component.
**Solution**: Add `'use client'` directive:
```typescript
// ✅ Add 'use client' at the top
'use client'
import { useState } from 'react'
export function Counter() {
const [count, setCount] = useState(0)
return
}
```
---
### 7. Error: `middleware.ts` is deprecated
**Warning**:
```
Warning: middleware.ts is deprecated. Use proxy.ts instead.
```
**Solution**: Migrate to `proxy.ts`:
```typescript
// Rename: middleware.ts → proxy.ts
// Rename function: middleware → proxy
export function proxy(request: NextRequest) {
// Same logic
}
```
---
### 8. Error: Turbopack build failure
**Error**:
```
Error: Failed to compile with Turbopack
```
**Cause**: Turbopack is now default in Next.js 16.
**Solution**: Opt out of Turbopack if incompatible:
```bash
npm run build -- --webpack
```
---
### 9. Error: Invalid `next/image` src
**Error**:
```
Invalid src prop (https://example.com/image.jpg) on `next/image`. Hostname "example.com" is not configured under images in your `next.config.js`
```
**Solution**: Add remote patterns in `next.config.ts`:
```typescript
const config: NextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
},
],
},
}
```
---
### 10. Error: Cannot import Server Component into Client Component
**Error**:
```
You're importing a Server Component into a Client Component
```
**Solution**: Pass Server Component as children:
```typescript
// ❌ Wrong
'use client'
import { ServerComponent } from './server-component' // Error
export function ClientComponent() {
return
}
// ✅ Correct
'use client'
export function ClientComponent({ children }: { children: React.ReactNode }) {
return
{children}
}
// Usage
{/* Pass as children */}
```
---
### 11. Error: `generateStaticParams` not working
**Cause**: `generateStaticParams` only works with static generation (`export const dynamic = 'force-static'`).
**Solution**:
```typescript
export const dynamic = 'force-static'
export async function generateStaticParams() {
const posts = await fetch('/api/posts').then(r => r.json())
return posts.map((post: { id: string }) => ({ id: post.id }))
}
```
---
### 12. Error: `fetch()` not caching
**Cause**: Next.js 16 uses opt-in caching with `"use cache"` directive.
**Solution**: Add `"use cache"` to component or function:
```typescript
'use cache'
export async function getPosts() {
const response = await fetch('/api/posts')
return response.json()
}
```
---
### 13. Error: Route collision with Route Groups
**Error**:
```
Error: Conflicting routes: /about and /(marketing)/about
```
**Cause**: Route groups create same URL path.
**Solution**: Ensure route groups don't conflict:
```
app/
├── (marketing)/about/page.tsx → /about
└── (shop)/about/page.tsx → ERROR: Duplicate /about
# Fix: Use different routes
app/
├── (marketing)/about/page.tsx → /about
└── (shop)/store-info/page.tsx → /store-info
```
---
### 14. Error: Metadata not updating
**Cause**: Using dynamic metadata without `generateMetadata()`.
**Solution**: Use `generateMetadata()` for dynamic pages:
```typescript
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise {
const { id } = await params
const post = await fetch(`/api/posts/${id}`).then(r => r.json())
return {
title: post.title,
description: post.excerpt,
}
}
```
---
### 15. Error: `next/font` font not loading
**Cause**: Font variable not applied to HTML element.
**Solution**: Apply font variable to `` or ``:
```typescript
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
{/* ✅ Apply variable */}
{children}
)
}
```
---
### 16. Error: Environment variables not available in browser
**Cause**: Server-only env vars are not exposed to browser.
**Solution**: Prefix with `NEXT_PUBLIC_` for client-side access:
```bash
# .env
SECRET_KEY=abc123 # Server-only
NEXT_PUBLIC_API_URL=https://api # Available in browser
```
```typescript
// Server Component (both work)
const secret = process.env.SECRET_KEY
const apiUrl = process.env.NEXT_PUBLIC_API_URL
// Client Component (only public vars work)
const apiUrl = process.env.NEXT_PUBLIC_API_URL
```
---
### 17. Error: Server Action not found
**Error**:
```
Error: Could not find Server Action
```
**Cause**: Missing `'use server'` directive.
**Solution**: Add `'use server'`:
```typescript
// ❌ Before
export async function createPost(formData: FormData) {
await db.posts.create({ ... })
}
// ✅ After
'use server'
export async function createPost(formData: FormData) {
await db.posts.create({ ... })
}
```
---
### 18. Error: TypeScript path alias not working
**Cause**: Incorrect `baseUrl` or `paths` in `tsconfig.json`.
**Solution**: Configure correctly:
```json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"],
"@/components/*": ["./app/components/*"]
}
}
}
```
**See Reference**: `references/top-errors.md`
---
### 19. Error: Client-side navigation throttled with multiple redirects
**Error**: `Throttling navigation to prevent the browser from hanging`
**Source**: [GitHub Issue #87245](https://github.com/vercel/next.js/issues/87245)
**Cause**: When `proxy.ts` (or `middleware.ts`) performs a redirect to add query params AND a Server Component also calls `redirect()` to add different query params, client-side navigation via `` fails in production builds. This is a regression from Next.js 14 to 16.
**Symptoms**:
- Works in `next dev` (development mode)
- Works with direct URL access (full page load)
- Fails with client-side navigation via `` in production build
- Prefetch causes infinite redirect loop
**Solution**: Disable prefetch on links that navigate to pages with redirect logic:
```typescript
// ✅ Workaround: Disable prefetch
Navigate
```
---
### 20. Error: Cache Components fail with i18n dynamic segments
**Error**: Route becomes dynamic despite `generateStaticParams`
**Source**: [GitHub Issue #86870](https://github.com/vercel/next.js/issues/86870)
**Cause**: Cache components (`"use cache"` directive) do NOT work on dynamic segments when using internationalization (i18n) frameworks like `intlayer`, `next-intl`, or `lingui`. Accessing `params` forces the route to be dynamic, even with `generateStaticParams` at the layout level.
**Why It Happens**: Every i18n framework requires accessing `params` to get the locale. Accessing `params` is an async call in Next.js 16, which opts the entire page out of caching.
**Solution**: Add `generateStaticParams` at EACH dynamic segment level:
```typescript
// app/[locale]/[id]/page.tsx
export async function generateStaticParams() {
return [
{ locale: 'en', id: '1' },
{ locale: 'en', id: '2' },
// ... all combinations
];
}
'use cache'
export default async function Page({ params }: Props) {
// Now caching works
}
```
**Additional Context**: The `[locale]` dynamic segment receives invalid values like `_next` during compilation, causing `RangeError: Incorrect locale information provided` when initializing i18n providers.
---
### 21. Error: instanceof fails for custom error classes in Server Components
**Error**: `instanceof CustomError` returns `false` even though it is CustomError
**Source**: [GitHub Issue #87614](https://github.com/vercel/next.js/issues/87614)
**Cause**: Module duplication in Server Components causes custom error classes to be loaded twice, creating different prototypes.
**Solution**: Use `error.name` or `error.constructor.name` instead of `instanceof`:
```typescript
// ❌ Wrong: instanceof doesn't work
try {
throw new CustomError('Test error');
} catch (error) {
if (error instanceof CustomError) { // ❌ false
// Never reached
}
}
// ✅ Correct: Use error.name
try {
throw new CustomError('Test error');
} catch (error) {
if (error instanceof Error && error.name === 'CustomError') { // ✅ true
// Handle CustomError
}
}
// ✅ Alternative: Use constructor.name
if (error.constructor.name === 'CustomError') {
// Handle CustomError
}
```
---
### 22. Error: TypeScript doesn't catch non-serializable props to Client Components
**Error**: Runtime error when passing functions/class instances to Client Components
**Source**: [GitHub Issue #86748](https://github.com/vercel/next.js/issues/86748)
**Cause**: The Next.js TypeScript plugin doesn't catch non-serializable props being passed from Server Components to Client Components. This causes runtime errors that are not detected at compile time.
**Why It Happens**: Only serializable data (JSON-compatible) can cross the Server/Client boundary. Functions, class instances, and Symbols cannot be serialized.
**Solution**: Only pass serializable props:
```typescript
// ❌ Wrong: Function not serializable
const user = {
name: 'John',
getProfile: () => console.log('profile'), // ❌ Not serializable
};
// ✅ Correct: Only serializable props
interface SerializableUser {
name: string;
email: string;
// No functions, no class instances, no Symbols
}
// ✅ Alternative: Create functions in Client Component
'use client';
export default function ClientComponent({ user }: { user: { name: string } }) {
const getProfile = () => console.log('profile'); // Define in client
return
{user.name}
;
}
```
**Runtime Validation**:
```typescript
import { z } from 'zod';
const UserSchema = z.object({
name: z.string(),
email: z.string(),
});
type User = z.infer;
```
---
### 23. Error: Turbopack production build fails with Prisma
**Error**: `The 'path' argument must be of type string`
**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721)
**Cause**: Turbopack production builds fail with Prisma ORM (v6.5.0+).
**Solution**: Use webpack for production builds:
```bash
npm run build -- --webpack
```
Or disable Turbopack in config:
```typescript
// next.config.ts
const config: NextConfig = {
experimental: {
turbo: false,
},
};
```
---
### 24. Error: Turbopack exposes source code via source maps
**Error**: Source code visible in production builds
**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721)
**Cause**: Turbopack always builds production source maps for the browser, exposing source code.
**Solution**: Disable production source maps:
```typescript
// next.config.ts
const config: NextConfig = {
productionBrowserSourceMaps: false,
};
```
Or exclude `.map` files in deployment:
```bash
# .vercelignore
*.map
```
---
### 25. Error: Module not found in production (Turbopack monorepo)
**Error**: `Module not found` in production despite successful local build
**Source**: [GitHub Issue #87737](https://github.com/vercel/next.js/issues/87737)
**Cause**: Turbopack generates external module references with hashes that don't match when `node_modules` structure differs (pnpm, yarn workspaces, monorepos).
**Symptoms**:
- Build succeeds locally but fails in CI/CD
- Hash mismatches between bundled references and actual module files
**Solution**: Explicitly externalize packages:
```typescript
// next.config.ts
const config: NextConfig = {
experimental: {
serverExternalPackages: ['package-name'],
},
};
```
---
**See Reference**: `references/top-errors.md`
---
## Templates & Resources
**Next.js 16-Specific Templates** (in `templates/`):
- `app-router-async-params.tsx` - Async params migration patterns
- `parallel-routes-with-default.tsx` - Required default.js files
- `cache-component-use-cache.tsx` - Cache Components with `"use cache"`
- `revalidate-tag-cache-life.ts` - Updated `revalidateTag()` with cacheLife
- `server-action-update-tag.ts` - `updateTag()` for read-your-writes
- `proxy-migration.ts` - Migrate from middleware.ts to proxy.ts
- `view-transitions-react-19.tsx` - React 19.2 View Transitions
- `next.config.ts` - Next.js 16 configuration
**Bundled References** (in `references/`):
- `next-16-migration-guide.md` - Complete Next.js 15→16 migration guide
- `cache-components-guide.md` - Cache Components deep dive
- `proxy-vs-middleware.md` - Proxy.ts vs middleware.ts
- `async-route-params.md` - Async params breaking change details
- `react-19-integration.md` - React 19.2 features in Next.js 16
- `top-errors.md` - 18+ common errors with solutions
**External Documentation**:
- **Next.js 16 Blog**: https://nextjs.org/blog/next-16
- **Next.js Docs**: https://nextjs.org/docs
- **Context7 MCP**: `/websites/nextjs` for latest reference
---
## Version Compatibility
| Package | Minimum Version | Recommended |
|---------|----------------|-------------|
| Next.js | 16.0.0 | 16.1.1+ |
| React | 19.2.0 | 19.2.3+ |
| Node.js | 20.9.0 | 20.9.0+ |
| TypeScript | 5.1.0 | 5.7.0+ |
| Turbopack | (built-in) | Stable |
**Check Versions**:
```bash
./scripts/check-versions.sh
```
---
## Token Efficiency
**Estimated Token Savings**: 65-70%
**Without Skill** (manual setup from docs):
- Read Next.js 16 migration guide: ~5k tokens
- Read App Router docs: ~8k tokens
- Read Server Actions docs: ~4k tokens
- Read Metadata API docs: ~3k tokens
- Trial-and-error fixes: ~8k tokens
- **Total**: ~28k tokens
**With Skill**:
- Load skill: ~8k tokens
- Use templates: ~2k tokens
- **Total**: ~10k tokens
- **Savings**: ~18k tokens (~64%)
**Errors Prevented**: 25 documented errors = 100% error prevention
---
## Maintenance
**Last Verified**: 2026-01-21
**Skill Version**: 3.1.0
**Changes**: Added 7 new errors (navigation throttling, i18n caching, Turbopack limitations, instanceof failures, non-serializable props). Expanded async params codemod limitations, caching defaults, and parallel routes edge cases.
**Next Review**: 2026-04-21 (Quarterly)
**Maintainer**: Jezweb | jeremy@jezweb.net
**Repository**: https://github.com/jezweb/claude-skills
**Update Triggers**:
- Next.js major/minor releases
- React major releases
- Breaking changes in APIs
- New Turbopack features
**Version Check**:
```bash
cd skills/nextjs
./scripts/check-versions.sh
```
---
**End of SKILL.md**