$npx -y skills add vercel-labs/openreview --skill next-best-practicesNext.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling
| 1 | # Next.js Best Practices |
| 2 | |
| 3 | Apply these rules when writing or reviewing Next.js code. |
| 4 | |
| 5 | ## File Conventions |
| 6 | |
| 7 | See [file-conventions.md](./file-conventions.md) for: |
| 8 | - Project structure and special files |
| 9 | - Route segments (dynamic, catch-all, groups) |
| 10 | - Parallel and intercepting routes |
| 11 | - Middleware rename in v16 (middleware → proxy) |
| 12 | |
| 13 | ## RSC Boundaries |
| 14 | |
| 15 | Detect invalid React Server Component patterns. |
| 16 | |
| 17 | See [rsc-boundaries.md](./rsc-boundaries.md) for: |
| 18 | - Async client component detection (invalid) |
| 19 | - Non-serializable props detection |
| 20 | - Server Action exceptions |
| 21 | |
| 22 | ## Async Patterns |
| 23 | |
| 24 | Next.js 15+ async API changes. |
| 25 | |
| 26 | See [async-patterns.md](./async-patterns.md) for: |
| 27 | - Async `params` and `searchParams` |
| 28 | - Async `cookies()` and `headers()` |
| 29 | - Migration codemod |
| 30 | |
| 31 | ## Runtime Selection |
| 32 | |
| 33 | See [runtime-selection.md](./runtime-selection.md) for: |
| 34 | - Default to Node.js runtime |
| 35 | - When Edge runtime is appropriate |
| 36 | |
| 37 | ## Directives |
| 38 | |
| 39 | See [directives.md](./directives.md) for: |
| 40 | - `'use client'`, `'use server'` (React) |
| 41 | - `'use cache'` (Next.js) |
| 42 | |
| 43 | ## Functions |
| 44 | |
| 45 | See [functions.md](./functions.md) for: |
| 46 | - Navigation hooks: `useRouter`, `usePathname`, `useSearchParams`, `useParams` |
| 47 | - Server functions: `cookies`, `headers`, `draftMode`, `after` |
| 48 | - Generate functions: `generateStaticParams`, `generateMetadata` |
| 49 | |
| 50 | ## Error Handling |
| 51 | |
| 52 | See [error-handling.md](./error-handling.md) for: |
| 53 | - `error.tsx`, `global-error.tsx`, `not-found.tsx` |
| 54 | - `redirect`, `permanentRedirect`, `notFound` |
| 55 | - `forbidden`, `unauthorized` (auth errors) |
| 56 | - `unstable_rethrow` for catch blocks |
| 57 | |
| 58 | ## Data Patterns |
| 59 | |
| 60 | See [data-patterns.md](./data-patterns.md) for: |
| 61 | - Server Components vs Server Actions vs Route Handlers |
| 62 | - Avoiding data waterfalls (`Promise.all`, Suspense, preload) |
| 63 | - Client component data fetching |
| 64 | |
| 65 | ## Route Handlers |
| 66 | |
| 67 | See [route-handlers.md](./route-handlers.md) for: |
| 68 | - `route.ts` basics |
| 69 | - GET handler conflicts with `page.tsx` |
| 70 | - Environment behavior (no React DOM) |
| 71 | - When to use vs Server Actions |
| 72 | |
| 73 | ## Metadata & OG Images |
| 74 | |
| 75 | See [metadata.md](./metadata.md) for: |
| 76 | - Static and dynamic metadata |
| 77 | - `generateMetadata` function |
| 78 | - OG image generation with `next/og` |
| 79 | - File-based metadata conventions |
| 80 | |
| 81 | ## Image Optimization |
| 82 | |
| 83 | See [image.md](./image.md) for: |
| 84 | - Always use `next/image` over `<img>` |
| 85 | - Remote images configuration |
| 86 | - Responsive `sizes` attribute |
| 87 | - Blur placeholders |
| 88 | - Priority loading for LCP |
| 89 | |
| 90 | ## Font Optimization |
| 91 | |
| 92 | See [font.md](./font.md) for: |
| 93 | - `next/font` setup |
| 94 | - Google Fonts, local fonts |
| 95 | - Tailwind CSS integration |
| 96 | - Preloading subsets |
| 97 | |
| 98 | ## Bundling |
| 99 | |
| 100 | See [bundling.md](./bundling.md) for: |
| 101 | - Server-incompatible packages |
| 102 | - CSS imports (not link tags) |
| 103 | - Polyfills (already included) |
| 104 | - ESM/CommonJS issues |
| 105 | - Bundle analysis |
| 106 | |
| 107 | ## Scripts |
| 108 | |
| 109 | See [scripts.md](./scripts.md) for: |
| 110 | - `next/script` vs native script tags |
| 111 | - Inline scripts need `id` |
| 112 | - Loading strategies |
| 113 | - Google Analytics with `@next/third-parties` |
| 114 | |
| 115 | ## Hydration Errors |
| 116 | |
| 117 | See [hydration-error.md](./hydration-error.md) for: |
| 118 | - Common causes (browser APIs, dates, invalid HTML) |
| 119 | - Debugging with error overlay |
| 120 | - Fixes for each cause |
| 121 | |
| 122 | ## Suspense Boundaries |
| 123 | |
| 124 | See [suspense-boundaries.md](./suspense-boundaries.md) for: |
| 125 | - CSR bailout with `useSearchParams` and `usePathname` |
| 126 | - Which hooks require Suspense boundaries |
| 127 | |
| 128 | ## Parallel & Intercepting Routes |
| 129 | |
| 130 | See [parallel-routes.md](./parallel-routes.md) for: |
| 131 | - Modal patterns with `@slot` and `(.)` interceptors |
| 132 | - `default.tsx` for fallbacks |
| 133 | - Closing modals correctly with `router.back()` |
| 134 | |
| 135 | ## Self-Hosting |
| 136 | |
| 137 | See [self-hosting.md](./self-hosting.md) for: |
| 138 | - `output: 'standalone'` for Docker |
| 139 | - Cache handlers for multi-instance ISR |
| 140 | - What works vs needs extra setup |
| 141 | |
| 142 | ## Debug Tricks |
| 143 | |
| 144 | See [debug-tricks.md](./debug-tricks.md) for: |
| 145 | - MCP endpoint for AI-assisted debugging |
| 146 | - Rebuild specific routes with `--debug-build-paths` |