react-nextjs

Next.js App Router Best Practices

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-nextjs" with this command: npx skills add alicoder001/agent-skills/alicoder001-agent-skills-react-nextjs

Next.js App Router Best Practices

Next.js 14+ with Vercel optimization patterns.

Instructions

  1. App Router Structure

app/ ├── layout.tsx # Root layout ├── page.tsx # Home page ├── loading.tsx # Loading UI ├── error.tsx # Error UI ├── not-found.tsx # 404 page ├── (auth)/ # Route group │ ├── login/ │ └── register/ └── api/ └── users/ └── route.ts # API route

  1. Server vs Client Components

// ✅ Server Component (default) - no directive async function UserList() { const users = await getUsers(); // Direct DB access return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>; }

// ✅ Client Component - needs interactivity 'use client'; function Counter() { const [count, setCount] = useState(0); return <button onClick={() => setCount(c => c + 1)}>{count}</button>; }

  1. Prevent Request Waterfall

// ❌ Bad - sequential (waterfall) async function Page() { const user = await getUser(); const posts = await getPosts(user.id); const comments = await getComments(posts[0].id); return ...; }

// ✅ Good - parallel with Promise.all async function Page() { const [user, posts] = await Promise.all([ getUser(), getPosts() ]); return ...; }

// ✅ Good - defer non-critical async function Page() { const user = await getUser(); const postsPromise = getPosts(user.id); // Don't await yet

return ( <div> <UserProfile user={user} /> <Suspense fallback={<PostsSkeleton />}> <Posts promise={postsPromise} /> </Suspense> </div> ); }

  1. No Barrel Files (Bundle Optimization)

// ❌ Bad - barrel file imports entire module import { Button, Card } from '@/components';

// ✅ Good - direct imports import { Button } from '@/components/Button'; import { Card } from '@/components/Card';

  1. Dynamic Imports

// ✅ Lazy load heavy components import dynamic from 'next/dynamic';

const HeavyChart = dynamic(() => import('@/components/Chart'), { loading: () => <ChartSkeleton />, ssr: false });

  1. Server Actions

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

import { revalidatePath } from 'next/cache';

export async function createPost(formData: FormData) { const title = formData.get('title');

await db.post.create({ data: { title } });

revalidatePath('/posts'); }

// Usage in component <form action={createPost}> <input name="title" /> <button type="submit">Create</button> </form>

  1. Caching Strategies

// ✅ React.cache for request deduplication import { cache } from 'react';

export const getUser = cache(async (id: string) => { return await db.user.findUnique({ where: { id } }); });

// ✅ Next.js fetch cache const data = await fetch(url, { next: { revalidate: 3600 } // Revalidate hourly });

// ✅ Static generation export const dynamic = 'force-static';

  1. Metadata

// Static metadata export const metadata: Metadata = { title: 'My App', description: 'Description...' };

// Dynamic metadata export async function generateMetadata({ params }): Promise<Metadata> { const product = await getProduct(params.id); return { title: product.name }; }

References

  • Next.js Documentation

  • Vercel Blog

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

solid

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

reasoning

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

collaboration

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

find-skills

No summary provided by upstream source.

Repository SourceNeeds Review