thinkfleetai/thinkfleet-engine

nextjs-patterns

Next.js App Router patterns: Server Components, data fetching, routing, middleware, caching, and deployment.

First seen Mar 1, 2026

Installation

$ npx skills add thinkfleetai/thinkfleet-engine --skill nextjs-patterns

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from thinkfleetai/thinkfleet-engine · top by installs.

npx skills add thinkfleetai/thinkfleet-engine

Browse all from thinkfleetai/thinkfleet-engine

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 3,662 B
  • docs SUMMARY.md 131 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Next.js Patterns

Modern Next.js with App Router, Server Components, and production patterns.

App Router Structure

app/
  layout.tsx        # Root layout (wraps all pages)
  page.tsx          # Home page (/)
  loading.tsx       # Loading UI (automatic Suspense)
  error.tsx         # Error boundary
  not-found.tsx     # 404 page
  api/
    route.ts        # API route (/api)
  dashboard/
    layout.tsx      # Nested layout
    page.tsx         # Dashboard page (/dashboard)
    [id]/
      page.tsx       # Dynamic route (/dashboard/123)

Server Components (default)

// app/users/page.tsx — runs on server, no client JS
async function UsersPage() {
  const users = await db.users.findMany(); // Direct DB access
  return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

Client Components

'use client'; // Only add when you need interactivity

import { useState } from 'react';

export function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

Data Fetching

Server Component (preferred)

// Fetch in the component — no useEffect needed
async function ProductPage({ params }: { params: { id: string } }) {
  const product = await fetch(`https://api.example.com/products/${params.id}`, {
    next: { revalidate: 3600 }, // Cache for 1 hour
  }).then(r => r.json());

  return <Product data={product} />;
}

Server Actions (mutations)

// app/actions.ts
'use server';

export async function createUser(formData: FormData) {
  const name = formData.get('name') as string;
  await db.users.create({ data: { name } });
  revalidatePath('/users');
}

// In component:
<form action={createUser}>
  <input name="name" />
  <button type="submit">Create</button>
</form>

API Routes

// app/api/users/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
  const users = await db.users.findMany();
  return NextResponse.json(users);
}

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

Middleware

// middleware.ts (root level)
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

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

export const config = { matcher: ['/dashboard/:path*'] };

Commands

# Dev server
npx next dev

# Production build
npx next build

# Start production server
npx next start

# Lint
npx next lint

# Analyze bundle
ANALYZE=true npx next build

Notes

  • Default to Server Components. Only add 'use client' when you need useState, useEffect, or browser APIs.
  • Server Components can await directly — no loading states needed (use loading.tsx for automatic Suspense).
  • fetch in Server Components is automatically deduped and cached.
  • Use revalidatePath() or revalidateTag() to invalidate cache after mutations.
  • Keep Client Components small and push them to leaf nodes of the component tree.