CRITICAL: In Next.js 15+, the `params` prop is a Promise and MUST be handled asynchronously. Follow these rules:
1. ALWAYS type params as Promise:
- Single param: Promise<{ slug: string }>
- Multiple params: Promise<{ categoryId: string; itemId: string }>
- Catch-all: Promise<{ slug: string[] }>
- Optional catch-all: Promise<{ slug?: string[] }>
2. ALWAYS use async/await pattern:
- Make component function async: export default async function MyPage({ params })
- Await params before accessing: const { slug } = await params;
- NEVER access params directly: params.slug is INCORRECT
3. Apply to ALL dynamic route files:
- Pages: app/[slug]/page.tsx
- Layouts: app/[slug]/layout.tsx
- Route handlers: app/api/[id]/route.ts
- All HTTP methods (GET, POST, PUT, DELETE, etc.)
4. Alternative: Use React's use() hook:
- Import: import { use } from 'react';
- Usage: const { slug } = use(params);
5. Proper error handling:
- Wrap in try/catch: try { const { slug } = await params; } catch { return <ErrorPage />; }
6. generateStaticParams should return objects matching param structure:
- [slug] → [{ slug: 'value' }]
- [categoryId]/[itemId] → [{ categoryId: 'cat', itemId: 'item' }]
7. FORBIDDEN patterns (will cause errors):
- const { slug } = params; // Synchronous access
- params.slug // Direct property access
- Non-async functions with param access
Remember: Synchronous access is deprecated in Next.js 15+ and will be removed.