Skip to Content

Next.js

Next.js framework rules from @next/eslint-plugin-next, applied to TypeScript and TSX sources inside Next.js apps.

Checks Next.js-specific conventions that the framework’s runtime treats as load-bearing: pages/app routing, <Head> placement, font and script loading, image and link components.

Source: @next/eslint-plugin-next (MIT).

Rule index

Each rule name links to the detailed section below.

Examples come from the checked lint corpus or package-level rule tests when project layout matters.

Rules

nextjs/google-font-display

Require a non-blocking display= value on Google Fonts stylesheet links; reject auto, block, and fallback, which keep text invisible while the font loads and hurt LCP. Prefer optional or swap.

Example:

// reports: nextjs/google-font-display (error) const a = ( <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter" /> );

nextjs/google-font-preconnect

Require rel="preconnect" for fonts.gstatic.com links to shave latency off Google Font fetches.

Example:

// reports: nextjs/google-font-preconnect (error) const a = <link href="https://fonts.gstatic.com" />;

nextjs/inline-script-id

Require an id attribute on inline <Script> components from next/script.

Next.js uses the id to track the script across client navigations and to satisfy its loading-strategy budget; an inline script without one is silently dropped on subsequent renders.

Example:

import Script from "next/script"; const a = ( // reports: nextjs/inline-script-id (error) <Script>{`console.log("hi")`}</Script> );

nextjs/next-script-for-ga

Prefer the Next.js Google Analytics integration over hand-written gtag script tags.

Example:

// reports: nextjs/next-script-for-ga (error) const a = ( <script async src="https://www.googletagmanager.com/gtag/js?id=GA_TRACKING_ID" /> );

nextjs/no-assign-module-variable

Reject local declarations named module, which shadow the CommonJS module binding Next.js relies on.

Example:

// reports: nextjs/no-assign-module-variable (error) const module = {};

nextjs/no-async-client-component

Reject async function bodies on React Client Components.

The client-side React runtime can’t await a component’s render, so an async "use client" component returns a pending promise that crashes hydration; do data fetching in a Server Component or in useEffect instead.

Example:

"use client"; // reports: nextjs/no-async-client-component (error) export async function Page() { return <div>hi</div>; }

nextjs/no-before-interactive-script-outside-document

Restrict the next/script strategy="beforeInteractive" option to pages/_document.tsx, anywhere else, the strategy is downgraded silently.

Example:

import Script from "next/script"; // reports: nextjs/no-before-interactive-script-outside-document (error) const a = <Script src="/x.js" strategy="beforeInteractive" />;

nextjs/no-css-tags

Reject raw <link rel="stylesheet"> tags.

Next.js handles CSS through its bundler, imported stylesheets, CSS Modules, or next/font, and manual stylesheet links skip the runtime’s critical-CSS extraction and render-blocking heuristics.

Example:

// reports: nextjs/no-css-tags (error) const a = <link rel="stylesheet" href="/styles.css" />;

nextjs/no-document-import-in-page

Restrict next/document imports to pages/_document.tsx, Document cannot be used in a regular page.

Example:

// reports: nextjs/no-document-import-in-page (error) import Document from "next/document";

nextjs/no-duplicate-head

Reject more than one <Head> element from next/document in pages/_document.tsx.

Next.js merges metadata into the single <Head> it renders into the HTML shell; additional instances are dropped silently and any tags inside them never reach the page.

Example:

const a = ( <> <Head /> {/* reports: nextjs/no-duplicate-head (error) */} <Head /> </> );

nextjs/no-head-element

Reject raw <head> elements outside the app/ directory, use next/head or the metadata exports.

Example:

// reports: nextjs/no-head-element (error) const a = ( <head> <title>Site</title> </head> );

nextjs/no-head-import-in-document

Reject next/head imports inside pages/_document.tsx, use next/document’s Head there.

Example:

// reports: nextjs/no-head-import-in-document (error) import Head from "next/head";

Prefer next/link for internal anchors with a static href, since Link performs client-side routing.

Example:

// reports: nextjs/no-html-link-for-pages (error) const a = <a href="/about">about</a>;

nextjs/no-img-element

Prefer next/image over raw <img> elements so the framework can optimize the asset.

Example:

// reports: nextjs/no-img-element (error) const a = <img src="/hero.png" alt="hero" />;

nextjs/no-page-custom-font

Reject Google font <link> tags inside regular pages files, load fonts in _document.tsx (pages router) or via next/font (app router).

Example:

// reports: nextjs/no-page-custom-font (error) const a = ( <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter&display=swap" /> );

nextjs/no-script-component-in-head

Reject next/script inside next/head, <Script> must appear in the JSX tree, not in <Head>.

Example:

const a = ( <Head> {/* reports: nextjs/no-script-component-in-head (error) */} <Script src="/x.js" /> </Head> );

nextjs/no-styled-jsx-in-document

Reject styled-jsx tags inside pages/_document.tsx, which the server renders incorrectly.

Example:

const a = ( <div> {/* reports: nextjs/no-styled-jsx-in-document (error) */} <style jsx>{` div { color: red; } `}</style> </div> );

nextjs/no-sync-scripts

Require async or defer on external raw <script> tags so loading does not block render.

Example:

// reports: nextjs/no-sync-scripts (error) const a = <script src="https://example.com/x.js" />;

nextjs/no-title-in-document-head

Reject <title> inside Head from next/document. Set the title from the metadata exports instead.

Example:

const a = ( <Head> {/* reports: nextjs/no-title-in-document-head (error) */} <title>Site</title> </Head> );

nextjs/no-typos

Catch near-miss typos in Next.js data-fetching export names (getStaticProps, getStaticPaths, getServerSideProps).

A misspelled export is treated as ordinary module state, so the page silently falls back to client-side rendering with no build-time warning.

Example:

// reports: nextjs/no-typos (error) export function getstaticprops() { return { props: {} }; }

nextjs/no-unwanted-polyfillio

Reject Polyfill.io script URLs, Next.js already polyfills modern browsers, and Polyfill.io has a checkered history.

Example:

// reports: nextjs/no-unwanted-polyfillio (error) const a = <script src="https://polyfill.io/v3/polyfill.min.js" />;
Last updated on