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.
- Do not await data fetching at the root of Server Components to enable streaming
- Suspend fallbacks should reserve layout space to prevent layout shifts
- Account for sticky headers with scroll-padding-top CSS when scrolling to element ids
- All exported functions under 'use server' or 'use cache' must be async
- Prevent XSS in JSON-LD by sanitizing strings
- Disable source maps in production to reduce memory usage
- Encode dynamic route segments in Link href with encodeURIComponent
- 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 cardsPrefer
<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 elementsPrefer
html { scroll-padding-top: 64px; } when header height is 64pxFlagged 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: truePrefer
productionBrowserSourceMaps: falseFlagged 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
Disallow <a> tags for internal Next.js page navigation
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.

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
Keep reading
- How to Write a Great PR Review CommentMost PR comments waste the author's time because they never say what they actually want. Here is the four-part format that fixes that.
- Repo-Aware AI Code Review vs. Diff-Based ReviewRepo-aware vs diff-based AI code review: diff review reads only the patch. Repo-aware review catches broken conventions, duplicate abstractions, and drift.
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.