← All skills
Tencent SkillHub · Developer Tools

Nextjs

Next.js App Router best practices — Server Components, data fetching, caching, routing, middleware, metadata, error handling, streaming, Server Actions, and performance optimization for Next.js 14-16+.

skill openclawclawhub Free
0 Downloads
0 Stars
0 Installs
0 Score
High Signal

Next.js App Router best practices — Server Components, data fetching, caching, routing, middleware, metadata, error handling, streaming, Server Actions, and performance optimization for Next.js 14-16+.

⬇ 0 downloads ★ 0 stars Unverified but indexed

Install for OpenClaw

Quick setup
  1. Download the package from Yavira.
  2. Extract the archive and review SKILL.md first.
  3. Import or place the package into your OpenClaw setup.

Requirements

Target platform
OpenClaw
Install method
Manual import
Extraction
Extract archive
Prerequisites
OpenClaw
Primary doc
SKILL.md

Package facts

Download mode
Yavira redirect
Package format
ZIP package
Source platform
Tencent SkillHub
What's included
README.md, SKILL.md, references/self-hosting.md, references/async-patterns.md, references/scripts.md, references/hydration-errors.md

Validation

  • Use the Yavira download entry.
  • Review SKILL.md after the package is downloaded.
  • Confirm the extracted package contains the expected setup assets.

Install with your agent

Agent handoff

Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.

  1. Download the package from Yavira.
  2. Extract it into a folder your agent can access.
  3. Paste one of the prompts below and point your agent at the extracted folder.
New install

I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.

Upgrade existing

I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.

Trust & source

Release facts

Source
Tencent SkillHub
Verification
Indexed source record
Version
1.0.0

Documentation

ClawHub primary doc Primary doc: SKILL.md 26 sections Open source page

Next.js App Router

Apply these patterns when building, reviewing, or debugging Next.js App Router applications.

OpenClaw / Moltbot / Clawbot

npx clawhub@latest install nextjs

WHEN

Building Next.js applications with App Router Migrating from Pages Router to App Router Implementing Server Components and streaming Setting up parallel and intercepting routes Optimizing data fetching and caching Building full-stack features with Server Actions Debugging hydration errors or RSC boundary issues

Rendering Modes

ModeWhereWhen to UseServer ComponentsServer onlyData fetching, secrets, heavy computationClient ComponentsBrowserInteractivity, hooks, browser APIsStatic (SSG)Build timeContent that rarely changesDynamic (SSR)Request timePersonalized or real-time dataStreamingProgressiveLarge pages, slow data sources

Server vs Client Decision Tree

Does it need...? ├── useState, useEffect, event handlers, browser APIs │ └── Client Component ('use client') ├── Direct data fetching, no interactivity │ └── Server Component (default) └── Both? └── Split: Server parent fetches data → Client child handles UI

File Conventions

See file-conventions.md for complete reference. app/ ├── layout.tsx # Shared UI wrapper (persists across navigations) ├── page.tsx # Route UI ├── loading.tsx # Suspense fallback (automatic) ├── error.tsx # Error boundary (must be 'use client') ├── not-found.tsx # 404 UI ├── route.ts # API endpoint (cannot coexist with page.tsx) ├── template.tsx # Like layout but re-mounts on navigation ├── default.tsx # Parallel route fallback └── opengraph-image.tsx # OG image generation Route segments: [slug] dynamic, [...slug] catch-all, [[...slug]] optional catch-all, (group) route group, @slot parallel route, _folder private (excluded from routing).

Data Fetching Patterns

Choose the right pattern for each use case. See data-patterns.md for full decision tree. PatternUse CaseCachingServer Component fetchInternal reads (preferred)Full Next.js cachingServer ActionMutations, form submissionsPOST only, no cacheRoute HandlerExternal APIs, webhooks, public RESTGET can be cachedClient fetch → APIClient-side reads (last resort)HTTP cache headers

Server Component Data Fetching (Preferred)

// app/products/page.tsx — Server Component by default export default async function ProductsPage() { const products = await db.product.findMany() // Direct DB access, no API layer return <ProductGrid products={products} /> }

Avoiding Data Waterfalls

// BAD: Sequential — each awaits before the next starts const user = await getUser() const posts = await getPosts() // GOOD: Parallel fetching const [user, posts] = await Promise.all([getUser(), getPosts()]) // GOOD: Streaming with Suspense — each section loads independently <Suspense fallback={<UserSkeleton />}><UserSection /></Suspense> <Suspense fallback={<PostsSkeleton />}><PostsSection /></Suspense>

Server Actions (Mutations)

// app/actions.ts 'use server' import { revalidateTag } from 'next/cache' export async function addToCart(productId: string) { const cookieStore = await cookies() const sessionId = cookieStore.get('session')?.value if (!sessionId) redirect('/login') await db.cart.upsert({ where: { sessionId_productId: { sessionId, productId } }, update: { quantity: { increment: 1 } }, create: { sessionId, productId, quantity: 1 }, }) revalidateTag('cart') return { success: true } }

Caching Strategy

MethodSyntaxUse CaseNo cachefetch(url, { cache: 'no-store' })Always-fresh dataStaticfetch(url, { cache: 'force-cache' })Rarely changesISRfetch(url, { next: { revalidate: 60 } })Time-based refreshTag-basedfetch(url, { next: { tags: ['products'] } })On-demand invalidation Invalidate from Server Actions: 'use server' import { revalidateTag, revalidatePath } from 'next/cache' export async function updateProduct(id: string, data: ProductData) { await db.product.update({ where: { id }, data }) revalidateTag('products') // Invalidate by tag revalidatePath('/products') // Invalidate by path }

RSC Boundaries

Props crossing Server → Client boundary must be JSON-serializable. See rsc-boundaries.md. Prop TypeValid?Fixstring, number, booleanYes—Plain object / arrayYes—Server Action ('use server')Yes—Function () => {}NoDefine inside client componentDate objectNoUse .toISOString()Map, Set, class instanceNoConvert to plain object/array Critical rule: Client Components cannot be async. Fetch data in a Server Component parent and pass it down.

Async APIs (Next.js 15+)

params, searchParams, cookies(), and headers() are all async. See async-patterns.md. // Pages and layouts — always await params type Props = { params: Promise<{ slug: string }> } export default async function Page({ params }: Props) { const { slug } = await params } // Server functions const cookieStore = await cookies() const headersList = await headers() // Non-async components — use React.use() import { use } from 'react' export default function Page({ params }: Props) { const { slug } = use(params) }

Route Organization

PatternSyntaxPurposeRoute groups(marketing)/Organize without affecting URLParallel routes@analytics/Multiple independent sections in one layoutIntercepting routes(.)photos/[id]Modal overlays on soft navigationPrivate folders_components/Exclude from routing

Parallel Routes & Modals

See parallel-routes.md for complete modal pattern. Key rules: Every @slot folder must have a default.tsx (returns null) or you get 404 on refresh Close modals with router.back(), never router.push() or <Link> Intercepting route matchers: (.) same level, (..) one level up, (...) from root

Metadata & SEO

See metadata.md for OG images, sitemaps, and file conventions. // Static metadata (layout or page) export const metadata: Metadata = { title: { default: 'My App', template: '%s | My App' }, description: 'Built with Next.js', } // Dynamic metadata export async function generateMetadata({ params }: Props): Promise<Metadata> { const { slug } = await params const post = await getPost(slug) return { title: post.title, description: post.description, openGraph: { images: [{ url: post.image, width: 1200, height: 630 }] }, } } Metadata is Server Components only. If a page has 'use client', extract metadata to a parent layout.

Error Handling

See error-handling.md for full patterns including auth errors. // app/blog/error.tsx — must be 'use client' 'use client' export default function Error({ error, reset }: { error: Error; reset: () => void }) { return ( <div> <h2>Something went wrong!</h2> <button onClick={() => reset()}>Try again</button> </div> ) } Critical gotcha: redirect(), notFound(), forbidden(), and unauthorized() throw special errors. Never catch them in try/catch: // BAD: redirect throw is caught — navigation fails! try { await db.post.create({ data }) redirect(`/posts/${post.id}`) } catch (error) { return { error: 'Failed' } // Catches the redirect too! } // GOOD: Call redirect outside try-catch let post try { post = await db.post.create({ data }) } catch (error) { return { error: 'Failed' } } redirect(`/posts/${post.id}`)

Streaming with Suspense

export default async function ProductPage({ params }: Props) { const { id } = await params const product = await getProduct(id) // Blocking — loads first return ( <div> <ProductHeader product={product} /> <Suspense fallback={<ReviewsSkeleton />}> <Reviews productId={id} /> {/* Streams in independently */} </Suspense> <Suspense fallback={<RecommendationsSkeleton />}> <Recommendations productId={id} /> {/* Streams in independently */} </Suspense> </div> ) }

Hooks That Require Suspense Boundaries

HookSuspense RequireduseSearchParams()Always (or entire page becomes CSR)usePathname()In dynamic routesuseParams()NouseRouter()No

Performance

Always use next/image over <img> — see image-optimization.md Always use next/link over <a> — client-side navigation with prefetching Always use next/font — see font-optimization.md Always use next/script — see scripts.md Set priority on above-the-fold images (LCP) Add sizes when using fill — without it, the largest image variant downloads Dynamic imports for heavy client components: const Chart = dynamic(() => import('./Chart')) Use generateStaticParams to pre-render dynamic routes at build time

Route Handlers

See route-handlers.md for API endpoint patterns.

Bundling

See bundling.md for fixing third-party package issues, server-incompatible packages, and ESM/CommonJS problems.

Hydration Errors

See hydration-errors.md for all causes and fixes. CauseFixBrowser APIs (window, localStorage)Client component with useEffect mount checknew Date().toLocaleString()Render on client with useEffectMath.random() for IDsUse useId() hook<p><div>...</div></p>Fix invalid HTML nestingThird-party scripts modifying DOMUse next/script with afterInteractive

Self-Hosting

See self-hosting.md for Docker, PM2, cache handlers, and deployment checklist. Key points: Use output: 'standalone' for Docker — creates minimal production bundle Copy public/ and .next/static/ separately (not included in standalone) Set HOSTNAME="0.0.0.0" for containers Multi-instance ISR requires a custom cache handler (Redis/S3) — filesystem cache breaks Set health check endpoint at /api/health

NEVER Do

NeverWhyInsteadAdd 'use client' by defaultBloats client bundle, loses Server Component benefitsServer Components are default — add 'use client' only for interactivityMake client components asyncNot supported — will crashFetch in Server Component parent, pass data as propsPass Date/Map/functions to clientNot serializable across RSC boundarySerialize to string/plain object, or use Server ActionsFetch from own API in Server ComponentsUnnecessary round-trip — you're already on the serverAccess DB/service directlyWrap redirect()/notFound() in try-catchThey throw special errors that get swallowedCall outside try-catch or use unstable_rethrow()Skip loading.tsx or Suspense fallbacksUsers see blank page during data loadingAlways provide loading statesUse useSearchParams without SuspenseEntire page silently falls back to CSRWrap in <Suspense> boundaryUse router.push() to close modalsBreaks history, modal can flash/persistUse router.back()Use @vercel/og for OG imagesBuilt into Next.js alreadyImport from next/ogOmit default.tsx in parallel route slotsHard navigation (refresh) returns 404Add default.tsx returning nullUse Edge runtime unless requiredLimited APIs, most npm packages breakDefault Node.js runtime covers 95% of casesSkip sizes prop on fill imagesDownloads largest image variant alwaysAdd sizes="100vw" or appropriate breakpointsImport fonts in multiple componentsCreates duplicate instancesImport once in layout, use CSS variableUse <link> for Google FontsNo optimization, blocks renderingUse next/font

Reference Files

FileTopicrsc-boundaries.mdServer/Client boundary rules, serializationdata-patterns.mdFetching decision tree, waterfall avoidanceerror-handling.mdError boundaries, redirect gotcha, auth errorsasync-patterns.mdNext.js 15+ async params/cookies/headersmetadata.mdSEO, OG images, sitemaps, file conventionsparallel-routes.mdModal pattern, intercepting routes, gotchashydration-errors.mdCauses, debugging, fixesself-hosting.mdDocker, PM2, cache handlers, deploymentfile-conventions.mdProject structure, special files, middlewarebundling.mdThird-party packages, SSR issues, Turbopackimage-optimization.mdnext/image best practicesfont-optimization.mdnext/font best practicesscripts.mdnext/script, third-party loadingroute-handlers.mdAPI endpoints, request/response helpers

Category context

Code helpers, APIs, CLIs, browser automation, testing, and developer operations.

Source: Tencent SkillHub

Largest current source with strong distribution and engagement signals.

Package contents

Included in package
6 Docs
  • SKILL.md Primary doc
  • README.md Docs
  • references/async-patterns.md Docs
  • references/hydration-errors.md Docs
  • references/scripts.md Docs
  • references/self-hosting.md Docs