Back to Rules

🧠 Cursor Rule — Next.js React Generalist Development

OfficialPopular
CursorJavaScript
javascriptnextjsreacttypescriptnodejsweb-development

Summary

Use Cursor to build predictable, scalable Next.js applications by validating server and client boundaries, preventing hydration mismatches, eliminating fetch waterfalls, and structuring UI around clear, testable rendering logic.

Objectives

  • Ensure SSR, RSC, and client hydration behave identically
  • Prevent layout shifts and runtime mismatches
  • Reduce unnecessary client-side fetching
  • Enforce clean server/client component separation
  • Detect rerender loops, waterfalls, and hydration issues through execution

Principles

1. Server components must remain pure and deterministic.

2. Client components are required when using state, effects, refs, or browser APIs.

3. Hydration must match SSR exactly.

4. Data should be fetched at the highest boundary possible.

5. Every rerender should have an explainable source.

Goal

Ensure consistent behavior across server rendering, RSC flows, and client hydration by using Cursor to surface mismatch errors, waterfall queries, rerender loops, and browser-only code leaks.

Rule Behavior

1️⃣ Validate Server vs Client Component Boundaries

  • Add "use client" only when browser APIs or interactivity are needed
  • Ask Cursor to inspect imports and detect unintended browser code in Server Components
  • Prevent unnecessary client-side JavaScript bundles

2️⃣ Ensure SSR and Hydration Output Match

Cursor can diff SSR HTML with hydrated DOM and show mismatches.

🟥 Before (Hydration Issue)

function Timestamp() {

return <div>{Date.now()}</div>;

}

Server returns a timestamp; client returns a new timestamp → mismatch.

🟩 After (Stable Hydration)

function Timestamp({ initialTime }) {

return <div>{initialTime}</div>;

}

export async function getServerSideProps() {

return { props: { initialTime: Date.now() } };

}

Cursor can highlight exactly where DOM differs.

3️⃣ Remove Fetch Waterfalls

Nested fetches cause slow sequential loading.

🟥 Before

function ProductsPage() {

return <List />;

}

function List() {

const [items, setItems] = useState([]);

useEffect(() => {

fetch('/api/items').then(r => r.json()).then(setItems);

}, []);

}

🟩 After

async function ProductsPage() {

const items = await getItems();

return <List items={items} />;

}

Now data loads once, server-friendly and cacheable.

4️⃣ Use Pure Rendering Helpers

Pure functions isolate UI logic and reduce rerenders.

Example:

function renderProducts(list) {

return list.map(item => <li key={item.id}>{item.name}</li>);

}

Cursor can extract this pattern automatically.

5️⃣ Trace Rerender Causes

Cursor can show rerender events and their exact triggers (prop changes, parent updates, context updates, unstable callbacks).

🟥 Before (Anti-Pattern)

"use client"

function Dashboard() {

const [data, setData] = useState([]);

useEffect(() => {

fetch('/api/stats').then(r => r.json()).then(setData);

}, []);

const width = window.innerWidth;

return <UI data={data} width={width} />;

}

Issues:

  • No SSR → layout shift
  • Slow client-side data loading
  • Browser APIs prevent server usage

🟩 After (Recommended Pattern)

async function Dashboard() {

const data = await getStats();

return <DashboardClient data={data} />;

}

"use client"

function DashboardClient({ data }) {

const width = typeof window !== 'undefined' ? window.innerWidth : null;

return <UI data={data} width={width} />;

}

Now SSR improves performance and hydration is stable.

Utilities

safeClient(fn) – wraps browser-only logic

wrapSSRData(loader) – ensures server-side fetching

useHydrationLog() – surfaces SSR vs hydration mismatches

Cursor Execution Steps

1. Capture SSR HTML

2. Hydrate and diff DOM

3. Navigate routes and log fetch calls

4. Trace rerender causes

5. Detect waterfalls and overfetching patterns

Agent Prompts

"Diff SSR HTML with hydrated DOM and show mismatches."

"Trace rerender sources for this component during navigation."

"Split this into server and client components while retaining behavior."

"Identify all fetch calls triggered and highlight waterfall chains."

Best Practices

  • Keep server components pure
  • Use client components minimally
  • Perform data fetching at the highest boundary
  • Validate hydration before release
  • Avoid mixing browser APIs into SSR code

Notes

Supports both App Router and Pages Router. Cursor is ideal for surfacing hydration issues, rerender sources, and data-fetching bottlenecks.

View Tool Page