All checklists

Next.js code review checklist

Next.js code review mistakes often come from rendering and streaming. This checklist covers the mistakes Revix flags in real pull requests. Look for an awaited data fetch that blocks streaming, Suspense fallbacks that shift the layout, and JSON-LD scripts that are not escaped against XSS. Each rule shows the code to flag, the fix and its source.

Oscar Estudillo
Updated
  1. Do not await data fetching at the root of Server Components to enable streaming
  2. Suspend fallbacks should reserve layout space to prevent layout shifts
  3. Account for sticky headers with scroll-padding-top CSS when scrolling to element ids
  4. All exported functions under 'use server' or 'use cache' must be async
  5. Prevent XSS in JSON-LD by sanitizing strings
  6. Disable source maps in production to reduce memory usage
  7. Encode dynamic route segments in Link href with encodeURIComponent
  8. Disallow <a> tags for internal Next.js page navigation

8 rules to check in every Next.js pull request

Revix reviews Next.js pull requests against 747 rules. This page shows a short list we picked from them. Each rule has a bad example, a good example and a source. We check each rule against its source and update the list every month. Rules marked as flagged by Revix have come up in real reviews.

Do not await data fetching at the root of Server Components to enable streaming

Streaming improves performance by sending static content first. Blocking with await delays streamed response and first contentful paint.

Avoid

export default async function Page() { const data = await fetchData(); return <Component data={data} /> }

Prefer

export default function Page() { const dataPromise = fetchData(); return <Suspense fallback={<Loading />}><Component dataPromise={dataPromise} /></Suspense> }

Flagged by Revix in real reviews · Performance · All current versions · Source: Streaming data to the client - Next.js Docs

Suspend fallbacks should reserve layout space to prevent layout shifts

CLS negatively impacts user experience and SEO ranking. Reserving space for unloaded content stabilizes layout as data streams in.

Avoid

<Suspense fallback={<p>Loading...</p>}><CardGrid /></Suspense> // fallback <p> is smaller height than final cards

Prefer

<Suspense fallback={<div style={{minHeight:'200px'}}>Loading...</div>}><CardGrid /></Suspense>

Flagged by Revix in real reviews · Performance · All current versions · Source: Streaming data to the client - Next.js Docs

Account for sticky headers with scroll-padding-top CSS when scrolling to element ids

Avoids content being hidden behind UI elements after hash navigation or scrollIntoView calls, improving UX.

Avoid

<header className="sticky top-0 h-16">...</header> without scroll-padding-top: 64px on html or scroll-margin-top on target elements

Prefer

html { scroll-padding-top: 64px; } when header height is 64px

Flagged by Revix in real reviews · Best practice · All current versions · Source: Link Component

All exported functions under 'use server' or 'use cache' must be async

Non-async exported functions in server or cache modules break assumptions about async invocation, serialization, and caching leading to unexpected behavior or errors.

Avoid

'use cache'
export function getData() { return {} }

Prefer

'use cache'
export async function getData() { return {} }

Flagged by Revix in real reviews · API usage · All current versions · Source: Cache Components and the use cache directive

Prevent XSS in JSON-LD by sanitizing strings

Preventing XSS vulnerabilities protects users and maintains application security, especially when rendering JSON-LD in script tags with `dangerouslySetInnerHTML`.

Avoid

<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />

Prefer

<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, '\\u003c') }} />

Flagged by Revix in real reviews · Security · All current versions · Source: JSON-LD Guidance

Disable source maps in production to reduce memory usage

Reducing source map generation reduces memory consumption and speeds up builds, helping avoid out-of-memory errors.

Avoid

productionBrowserSourceMaps: true

Prefer

productionBrowserSourceMaps: false

Flagged by Revix in real reviews · Performance · All current versions · Source: Preloading Entries

Encode dynamic route segments in Link href with encodeURIComponent

Without encoding, special characters in dynamic segments (like slashes, spaces, or unicode) can cause incorrect routing or malformed URLs which break navigation.

Avoid

<Link href={`/blog/${post.slug}`}>Post</Link>

Prefer

<Link href={`/blog/${encodeURIComponent(post.slug)}`}>Post</Link>

Flagged by Revix in real reviews · Best practice · All current versions · Source: Linking and Navigating

Using <a> tags for internal navigation bypasses Next.js' client-side routing capabilities, causing full page reloads and slower navigation.

Avoid

<a href="/about">About</a>

Prefer

import Link from 'next/link'; <Link href="/about">About</Link>

Flagged by Revix in real reviews · API usage · All current versions · Source: @next/eslint-plugin-next no-html-link-for-pages

How Revix applies these rules in pull requests

Revix matches these rules against the code each pull request changes. When a comment rests on one, it names the rule, so the author can read the reasoning and the source instead of taking the bot's word for it.

export default async function Page() { const data = await fetchData(); return <Component data={data} /> }

revixappdevBot

suggestion: Streaming improves performance by sending static content first. Blocking with await delays streamed response and first contentful paint.

📚 Rule (Next.js): Do not await data fetching at the root of Server Components to enable streaming

How the comment reads on a GitHub pull request when a change breaks the first rule on this page.

Reviews run natively on GitHub, GitLab and Bitbucket.

Revix also learns your team's own rules from the code you already merged. Start a free trial and see them on your next pull request.