# Next.js code review checklist

> Next.js code review checklist of the mistakes Revix flags in real pull requests, from awaits that block streaming to layout-shifting fallbacks.

Canonical URL: https://www.revix.ai/checklists/nextjs

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.

Author: Oscar Estudillo · Updated: 2026-10-30

## 8 rules to check in every Next.js pull request

### 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**

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

**Prefer**

```tsx
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](https://nextjs.org/docs/app/guides/streaming)

### 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**

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

**Prefer**

```tsx
<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](https://nextjs.org/docs/app/guides/streaming)

### 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**

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

**Prefer**

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

Flagged by Revix in real reviews · Best practice · All current versions · Source: [Link Component](https://nextjs.org/docs/app/api-reference/components/link)

### 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**

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

**Prefer**

```tsx
'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](https://nextjs.org/docs/app/api-reference/directives/use-cache)

### 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**

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

**Prefer**

```tsx
<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](https://nextjs.org/docs/app/guides/json-ld)

### 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**

```tsx
productionBrowserSourceMaps: true
```

**Prefer**

```tsx
productionBrowserSourceMaps: false
```

Flagged by Revix in real reviews · Performance · All current versions · Source: [Preloading Entries](https://nextjs.org/docs/app/guides/memory-usage)

### 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**

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

**Prefer**

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

Flagged by Revix in real reviews · Best practice · All current versions · Source: [Linking and Navigating](https://nextjs.org/docs/pages/building-your-application/routing/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**

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

**Prefer**

```tsx
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](https://nextjs.org/docs/messages/no-html-link-for-pages)
