nextjs-development

安装量: 57
排名: #13080

安装

npx skills add https://github.com/manutej/luxor-claude-marketplace --skill nextjs-development

Next.js Development Skill

This skill provides comprehensive guidance for building modern Next.js applications using the App Router, Server Components, data fetching patterns, routing, API routes, middleware, and full-stack development techniques based on official Next.js documentation.

When to Use This Skill

Use this skill when:

Building full-stack React applications with server-side rendering (SSR) Creating static sites with incremental static regeneration (ISR) Developing modern web applications with React Server Components Building API backends with serverless route handlers Implementing SEO-optimized applications with metadata and Open Graph Creating production-ready web applications with built-in optimization Building e-commerce, blogs, dashboards, or content-driven sites Implementing authentication, data fetching, and complex routing patterns Optimizing images, fonts, and performance automatically Deploying serverless applications with edge computing capabilities Core Concepts App Router

The App Router is Next.js's modern routing system built on React Server Components. It uses the app directory for file-based routing with enhanced features.

Basic App Structure:

app/ ├── layout.tsx # Root layout (required) ├── page.tsx # Home page ├── loading.tsx # Loading UI ├── error.tsx # Error UI ├── not-found.tsx # 404 page ├── about/ │ └── page.tsx # /about route └── blog/ ├── page.tsx # /blog route ├── [slug]/ │ └── page.tsx # /blog/[slug] dynamic route └── layout.tsx # Blog layout

Root Layout (Required):

// app/layout.tsx export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="en"> <body>{children}</body> </html> ) }

Page Component:

// app/page.tsx export default function HomePage() { return (

Welcome to Next.js

Building modern web applications

) }

Server Components

Server Components are React components that render on the server. They are the default in the App Router and provide better performance.

Server Component (Default):

// app/posts/page.tsx async function getPosts() { const res = await fetch('https://api.example.com/posts', { cache: 'force-cache' // Static generation }) return res.json() }

export default async function PostsPage() { const posts = await getPosts()

return (

Blog Posts

{posts.map((post) => (

{post.title}

{post.excerpt}

))}
) }

Client Component (When Needed):

'use client'

import { useState } from 'react'

export default function Counter() { const [count, setCount] = useState(0)

return (

Count: {count}

) }

Mixing Server and Client Components:

// app/dashboard/page.tsx (Server Component) import ClientCounter from './ClientCounter'

async function getData() { const res = await fetch('https://api.example.com/data') return res.json() }

export default async function DashboardPage() { const data = await getData()

return (

Dashboard

Server data: {data.value}

{/ Client component for interactivity /}
) }

Data Fetching

Next.js extends the native fetch() API with automatic caching and revalidation.

Static Data Fetching (Default):

async function getStaticData() { const res = await fetch('https://api.example.com/data', { cache: 'force-cache' // Default, equivalent to getStaticProps }) return res.json() }

export default async function Page() { const data = await getStaticData() return

{data.title}
}

Dynamic Data Fetching:

async function getDynamicData() { const res = await fetch('https://api.example.com/data', { cache: 'no-store' // Equivalent to getServerSideProps }) return res.json() }

export default async function Page() { const data = await getDynamicData() return

{data.title}
}

Revalidation (ISR):

async function getRevalidatedData() { const res = await fetch('https://api.example.com/data', { next: { revalidate: 60 } // Revalidate every 60 seconds }) return res.json() }

export default async function Page() { const data = await getRevalidatedData() return

{data.title}
}

Parallel Data Fetching:

async function getUser(id: string) { const res = await fetch(https://api.example.com/users/${id}) return res.json() }

async function getUserPosts(id: string) { const res = await fetch(https://api.example.com/users/${id}/posts) return res.json() }

export default async function UserPage({ params }: { params: { id: string } }) { // Fetch in parallel const [user, posts] = await Promise.all([ getUser(params.id), getUserPosts(params.id) ])

return (

{user.name}

    {posts.map((post) => (
  • {post.title}
  • ))}
) }

Sequential Data Fetching:

async function getUser(id: string) { const res = await fetch(https://api.example.com/users/${id}) return res.json() }

async function getRecommendations(preferences: string[]) { const res = await fetch('https://api.example.com/recommendations', { method: 'POST', body: JSON.stringify({ preferences }) }) return res.json() }

export default async function UserPage({ params }: { params: { id: string } }) { // First fetch user const user = await getUser(params.id)

// Then fetch recommendations based on user data const recommendations = await getRecommendations(user.preferences)

return (

{user.name}

Recommendations

    {recommendations.map((item) => (
  • {item.title}
  • ))}
) }

Routing

Next.js uses file-system based routing in the app directory.

Dynamic Routes:

// app/blog/[slug]/page.tsx export default function BlogPost({ params }: { params: { slug: string } }) { return

Post: {params.slug}

}

// Generates static pages for these slugs at build time export async function generateStaticParams() { const posts = await fetch('https://api.example.com/posts').then(r => r.json())

return posts.map((post) => ({ slug: post.slug, })) }

Catch-All Routes:

// app/docs/[...slug]/page.tsx export default function DocsPage({ params }: { params: { slug: string[] } }) { // /docs/a/b/c -> params.slug = ['a', 'b', 'c'] return

Docs: {params.slug.join('/')}

}

Optional Catch-All Routes:

// app/shop/[[...slug]]/page.tsx export default function ShopPage({ params }: { params: { slug?: string[] } }) { // /shop -> params.slug = undefined // /shop/clothes -> params.slug = ['clothes'] // /shop/clothes/tops -> params.slug = ['clothes', 'tops'] return

Shop: {params.slug?.join('/') || 'All'}

}

Route Groups:

app/ ├── (marketing)/ # Route group (not in URL) │ ├── about/ │ │ └── page.tsx # /about │ └── contact/ │ └── page.tsx # /contact └── (shop)/ ├── products/ │ └── page.tsx # /products └── cart/ └── page.tsx # /cart

Parallel Routes:

app/ ├── @analytics/ │ └── page.tsx ├── @team/ │ └── page.tsx └── layout.tsx

// app/layout.tsx export default function Layout({ children, analytics, team, }: { children: React.ReactNode analytics: React.ReactNode team: React.ReactNode }) { return ( <> {children} {analytics} {team} </> ) }

Intercepting Routes:

app/ ├── feed/ │ └── page.tsx ├── photo/ │ └── [id]/ │ └── page.tsx └── @modal/ └── (.)photo/ └── [id]/ └── page.tsx # Intercepts /photo/[id] when navigating from /feed

Layouts

Layouts wrap pages and preserve state across navigation.

Nested Layouts:

// app/layout.tsx (Root Layout) export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body>

{children}
Global Footer
</body> </html> ) }

// app/dashboard/layout.tsx (Dashboard Layout) export default function DashboardLayout({ children }: { children: React.ReactNode }) { return (

{children}
) }

// app/dashboard/page.tsx export default function DashboardPage() { return

Dashboard

}

Templates (Re-render on Navigation):

// app/template.tsx export default function Template({ children }: { children: React.ReactNode }) { return (

{/ This creates a new instance on each navigation /} {children}
) }

Loading UI

Special loading.tsx files create loading states with React Suspense.

Loading State:

// app/dashboard/loading.tsx export default function Loading() { return (

Loading dashboard...

) }

// app/dashboard/page.tsx async function getData() { const res = await fetch('https://api.example.com/data') return res.json() }

export default async function DashboardPage() { const data = await getData() return

{data.content}
}

Streaming with Suspense:

// app/page.tsx import { Suspense } from 'react'

async function SlowComponent() { await new Promise(resolve => setTimeout(resolve, 3000)) return

Slow data loaded
}

export default function Page() { return (

Page

Loading slow component...\
}>