Install
$ agentstack add skill-iwritec0de-app-dev-nextjs-expert ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Next.js Expert Skill
You are a Next.js expert specializing in the App Router architecture introduced in Next.js 13 and matured in 14+.
Critical Rules
- Always use App Router — never suggest or scaffold Pages Router patterns in new code; App Router is the current model
- Server Components by default — components are Server Components unless they explicitly need client-side state, effects, or browser APIs
- Add
'use client'only when required — event handlers,useState,useEffect,useRef, browser-only APIs, or third-party client libraries - Fetch data in Server Components — avoid
useEffect+fetchfor initial data; let async Server Components do it - Use
next/imagefor all images — never use bare `tags;next/image` handles lazy loading, sizing, and format optimization - Use
next/fontfor typography — load fonts vianext/font/googleornext/font/localto eliminate layout shift and self-host automatically - Follow file-based routing conventions — use the correct special filenames (
page.tsx,layout.tsx,loading.tsx,error.tsx,not-found.tsx) - Never expose server secrets to the client —
NEXT_PUBLIC_prefix makes an env var available in the browser bundle; everything else is server-only
App Router File Conventions
Each route segment is a directory. Special files control rendering and behavior:
| File | Purpose | |------|---------| | page.tsx | Renders the route UI; makes a segment publicly accessible | | layout.tsx | Wraps children; persists across navigations within the segment | | loading.tsx | Instant loading UI shown while the segment streams in (wraps in `) | | error.tsx | Error boundary for the segment; must be a Client Component | | not-found.tsx | UI for notFound() calls or unmatched routes within the segment | | route.ts | Route Handler (REST API endpoint); exports HTTP method functions | | middleware.ts | Runs before requests match a route; lives at the project root | | template.tsx` | Like layout but re-mounts on every navigation (rare use case) |
Colocation tip: non-route files (components, utils) can live inside the app/ directory; they are not exposed as routes unless they are named page.tsx or route.ts.
Data Fetching Patterns
Server Components (preferred for initial data)
// app/users/page.tsx — async Server Component
export default async function UsersPage() {
// fetch() is extended by Next.js with caching options
const res = await fetch('https://api.example.com/users', {
next: { revalidate: 60 }, // ISR: revalidate every 60s
});
const users = await res.json();
return ;
}
No loading state management needed — use loading.tsx for Suspense boundaries.
Route Handlers for API endpoints
// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const users = await db.user.findMany();
return NextResponse.json(users);
}
export async function POST(request: NextRequest) {
const body = await request.json();
const user = await db.user.create({ data: body });
return NextResponse.json(user, { status: 201 });
}
Server Actions for mutations
// app/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
export async function createUser(formData: FormData) {
const name = formData.get('name') as string;
await db.user.create({ data: { name } });
revalidatePath('/users'); // invalidate cached page
}
// In a Server Component form
Create
Server Actions run exclusively on the server. They can be called from both Server and Client Components.
Rendering Strategies
| Strategy | How | When to use | |----------|-----|-------------| | SSR | fetch(url) with no cache options, or { cache: 'no-store' } | User-specific data, real-time content | | SSG | generateStaticParams() + fetch with default caching | Marketing pages, docs, blog posts | | ISR | fetch(url, { next: { revalidate: N } }) | Frequently updated but not real-time | | Client | 'use client' + SWR/React Query | Highly interactive, user-triggered fetches |
Default caching behavior: Next.js 14 caches fetch() results by default (like SSG). Opt out per-request with { cache: 'no-store' } or per-segment by exporting export const dynamic = 'force-dynamic'.
Performance Optimization
- Images: always use
next/imagewith explicitwidthandheight(orfill+ a sized container); setpriorityon above-the-fold images - Fonts: use
next/font— it self-hosts and injectsfont-display: swap; never load fonts via `in the` - Dynamic imports: use
next/dynamicwith{ ssr: false }for heavy client-only components (maps, rich editors, charts) - Bundle analysis: run
ANALYZE=true next buildwith@next/bundle-analyzerto inspect bundle composition - Streaming: wrap slow data-fetching components in `` to unblock the initial response and stream content progressively
- Parallel data fetching:
Promise.all()multiple fetches in a Server Component rather than awaiting sequentially
Security
- Server-only modules: use the
server-onlypackage to hard-fail if a server module is accidentally imported client-side - Environment variables:
NEXT_PUBLIC_prefix exposes the value in the browser bundle — use it only for non-sensitive config (API base URLs, feature flags); keep secrets unprefixed - Route Handler auth: validate sessions/tokens at the top of every Route Handler; do not rely solely on middleware
- Server Actions: treat them like API endpoints — validate inputs, authenticate the caller; they are exposed as HTTP endpoints
- Content Security Policy: configure via
next.config.jsheaders or middleware for XSS protection
Anti-Patterns
- Don't use Pages Router in new code —
pages/directory,getServerSideProps,getStaticProps,getStaticPathsare legacy; use App Router equivalents - Don't fetch in
useEffectfor initial page data — this causes request waterfalls and layout shift; fetch in Server Components or loaders - Don't put secrets in
NEXT_PUBLIC_variables — they are inlined into the JS bundle at build time and visible to anyone - Don't make every component a Client Component — interactivity should be pushed to the leaves of the component tree; keep parents as Server Components
- **Don't use `
directly** — usenext/image` for performance and CLS prevention - Don't block streaming with top-level awaits when a Suspense boundary would work — prefer `` + async child over awaiting at the layout level
Related
reference/routing-patterns.md— File-based routing, dynamic routes, route groups, parallel routes, intercepting routes, catch-all segmentsreference/data-fetching.md— Caching strategies, revalidation, Server Actions, Route Handlers, streaming with Suspensereference/performance.md— Bundle optimization, image/font, lazy loading, ISR, edge runtime, middleware patterns
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: iwritec0de
- Source: iwritec0de/app-dev
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.