nextjs-patterns
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 needuseState,useEffect, or browser APIs. - Server Components can
awaitdirectly — no loading states needed (useloading.tsxfor automatic Suspense). fetchin Server Components is automatically deduped and cached.- Use
revalidatePath()orrevalidateTag()to invalidate cache after mutations. - Keep Client Components small and push them to leaf nodes of the component tree.
More from thinkfleetai/thinkfleet-engine
local-whisper
Local speech-to-text using OpenAI Whisper. Runs fully offline after model download. High quality transcription with multiple model sizes.
149flyio-cli-public
Use the Fly.io flyctl CLI for deploying and operating apps on Fly.io: deploys (local or remote builder), viewing status/logs, SSH/console, secrets/config, scaling, machines, volumes, and Fly Postgres (create/attach/manage databases). Use when asked to deploy to Fly.io, debug fly deploy/build/runtime failures, set up GitHub Actions deploys/previews, or safely manage Fly apps and Postgres.
24kagi-search
Web search using Kagi Search API. Use when you need to search the web for current information, facts, or references. Requires KAGI_API_KEY in the environment.
22feishu-bridge
Connect a Feishu (Lark) bot to ThinkFleet via WebSocket long-connection. No public server, domain, or ngrok required. Use when setting up Feishu/Lark as a messaging channel, troubleshooting the Feishu bridge, or managing the bridge service (start/stop/logs). Covers bot creation on Feishu Open Platform, credential setup, bridge startup, macOS launchd auto-restart, and group chat behavior tuning.
13video-subtitles
Generate SRT subtitles from video/audio with translation support. Transcribes Hebrew (ivrit.ai) and English (whisper), translates between languages, burns subtitles into video. Use for creating captions, transcripts, or hardcoded subtitles for WhatsApp/social media.
10freshrss
Query headlines and articles from a self-hosted FreshRSS instance. Use when the user asks for RSS news, latest headlines, feed updates, or wants to browse articles from their FreshRSS reader. Supports filtering by category, time range, and count.
9