mcpbeat Sign in

Nextjs Patterns Agent Skill

Next.js best practices, server components, app router patterns, caching strategies, and full-stack architecture

2k tokens
context cost
the whole folder, loaded on every use
1
files
instructions only
0
copies elsewhere
how many repositories repackaged it
365
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/cosmicstack-labs/mercury-agent-skills --skill nextjs-patterns

The instruction itself

17 sections, as written by the author

Next.js Patterns

Comprehensive guide to building production-grade Next.js applications with the App Router, Server Components, and modern React patterns.

Core Architecture

App Router vs Pages Router

| Aspect | App Router | Pages Router |

|--------|-----------|--------------|

| Components | Server Components by default | Client Components only |

| Routing | File-system based with layout nesting | File-system based, flat |

| Data Fetching | Server-side fetch, use, cache primitives | getServerSideProps, getStaticProps |

| Loading States | loading.js files | Manual implementation |

| Error Handling | error.js files | Manual implementation |

| Streaming | Built-in with Suspense boundaries | Not supported |

Project Structure

my-app/
├── app/
│   ├── layout.tsx          # Root layout
│   ├── page.tsx            # Home page
│   ├── loading.tsx         # Root loading state
│   ├── error.tsx           # Root error boundary
│   ├── not-found.tsx       # 404 page
│   ├── (auth)/             # Route group
│   │   ├── login/page.tsx
│   │   └── register/page.tsx
│   ├── dashboard/
│   │   ├── layout.tsx      # Dashboard layout
│   │   ├── page.tsx        # Dashboard home
│   │   ├── loading.tsx
│   │   └── settings/
│   │       └── page.tsx
│   └── api/
│       └── [...route]/route.ts  # API handlers
├── components/
│   ├── ui/                 # Shared UI components
│   └── features/           # Feature-specific components
├── lib/
│   ├── db.ts              # Database client
│   ├── auth.ts            # Auth utilities
│   └── utils.ts           # Shared utilities
└── public/
    └── images/

Server Components (RSC)

When to Use Server vs Client

// ✅ SERVER COMPONENT (default) — Use for:
// - Data fetching from databases/APIs
// - Accessing backend resources directly
// - Keeping sensitive logic on server
// - Reducing client bundle size
// - SEO-critical content
async function ProductPage({ params }: { params: { id: string } }) {
  const product = await db.product.findUnique({ where: { id: params.id } });
  return <ProductDetail product={product} />;
}

// ✅ CLIENT COMPONENT — Use for:
// - Interactivity (onClick, onChange, etc.)
// - useState, useReducer, useEffect
// - Browser-only APIs
// - Custom hooks
// - Event listeners
'use client';
function AddToCartButton({ productId }: { productId: string }) {
  const [added, setAdded] = useState(false);
  return (
    <button onClick={() => { addToCart(productId); setAdded(true); }}>
      {added ? 'Added!' : 'Add to Cart'}
    </button>
  );
}

Composing Server and Client Components

// ✅ CORRECT: Server Component wrapping Client Component
async function ProductPage({ id }: { id: string }) {
  const product = await getProduct(id);
  // Server component passes data as props to client component
  return (
    <div>
      <ProductDetails product={product} />
      <AddToCartButton productId={id} />
    </div>
  );
}

// ❌ WRONG: Client Component importing Server Component
'use client';
import ServerComponent from './ServerComponent'; // ❌ Won't work
function ClientPage() {
  return <ServerComponent />; // Error: Cannot import server component into client
}

// ✅ CORRECT: Pass Server Component as children
'use client';
function ClientLayout({ children }: { children: React.ReactNode }) {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
      {isOpen && children} {/* Server component rendered here */}
    </div>
  );
}

Data Fetching Patterns

Server-Side Data Fetching

// app/products/page.tsx
async function ProductsPage() {
  // Direct database access — no API route needed
  const products = await db.product.findMany({
    take: 20,
    orderBy: { createdAt: 'desc' },
  });
  
  return <ProductGrid products={products} />;
}

// With parallel fetching for multiple data sources
async function DashboardPage() {
  const [user, posts, analytics] = await Promise.all([
    getCurrentUser(),
    getRecentPosts(),
    getAnalytics(),
  ]);
  
  return (
    <DashboardShell user={user}>
      <PostList posts={posts} />
      <AnalyticsChart data={analytics} />
    </DashboardShell>
  );
}

Revalidation Strategies

// Time-based revalidation (ISR)
export const revalidate = 3600; // Revalidate every hour

// On-demand revalidation (revalidateTag / revalidatePath)
'use server';
export async function publishPost(formData: FormData) {
  const post = await createPost(formData);
  revalidateTag('posts');
  revalidatePath('/blog');
  redirect(`/blog/${post.slug}`);
}

// Dynamic data — no caching
export const dynamic = 'force-dynamic';

// Static data — cache forever
export const dynamic = 'force-static';

Streaming with Suspense

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

export default function DashboardPage() {
  return (
    <div>
      <h1>Dashboard</h1>
      <Suspense fallback={<DashboardSkeleton />}>
        <DashboardContent />
      </Suspense>
      <Suspense fallback={<ActivitySkeleton />}>
        <RecentActivity />
      </Suspense>
    </div>
  );
}

async function DashboardContent() {
  const data = await fetchDashboardData(); // This suspends
  return <DashboardCharts data={data} />;
}

async function RecentActivity() {
  const activity = await fetchRecentActivity(); // This loads independently
  return <ActivityFeed items={activity} />;
}

Route Handlers & API Patterns

// app/api/products/route.ts
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const page = parseInt(searchParams.get('page') || '1');
  const limit = parseInt(searchParams.get('limit') || '20');
  
  const products = await db.product.findMany({
    skip: (page - 1) * limit,
    take: limit,
  });
  
  return Response.json({ products, page, limit });
}

export async function POST(request: Request) {
  const body = await request.json();
  const product = await db.product.create({ data: body });
  return Response.json(product, { status: 201 });
}

Common Patterns

Route Groups for Organization

// app/(marketing)/page.tsx — Public marketing pages
// app/(dashboard)/page.tsx — Authenticated dashboard
// app/(auth)/login/page.tsx — Auth pages with different layout

Middleware for Auth

// middleware.ts
export function middleware(request: NextRequest) {
  const token = request.cookies.get('session');
  const { pathname } = request.nextUrl;
  
  // Protected routes
  if (pathname.startsWith('/dashboard') && !token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  
  return NextResponse.next();
}

Error Boundaries

// app/dashboard/error.tsx
'use client';
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={() => reset()}>Try again</button>
    </div>
  );
}

Common Mistakes

  • Overusing client components: Default to Server Components. Only add 'use client' when you need interactivity.
  • Nesting fetch calls sequentially: Use Promise.all() for independent data fetches.
  • Ignoring caching defaults: Understand Next.js fetch caching. Use no-store or revalidate explicitly.
  • Mixing server/client component boundaries incorrectly: Pass Server Components as children to Client Components, don't import them.
  • Forgetting error and loading states: Always provide error boundaries and loading skeletons for streaming.

Other skills for the same job

different authors, same section of the catalogue
MCP Builder
by anthropics
vendor ×13

Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

30k tokens scripts
Changelog Generator
by frostant
×9

Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.

774 tokens
Finishing A Development Branch
by ZhanlinCui
×7

Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup

1k tokens
MCP Builder
by JayZeeDesign
×7

Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

37k tokens scripts
Vercel React Native Skills
by vercel-labs
vendor ×6

React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.

39k tokens
Vercel React Best Practices
by ratacat
×5

React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.

34k tokens
Next Best Practices
by vercel-labs
vendor ×4

Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling

20k tokens
Using Git Worktrees
by ZhanlinCui
×4

Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification

1k tokens

How to use it

Copy the folder

Take cosmicstack-labs/nextjs-patterns from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.