Hiprup

What is the _document.js file and when would you customize it?

_document.tsx is a special file in the Pages Router that lets you customize the HTML document Next.js sends — the <html>, <head>, and <body> tags around your app. It runs only on the server, never on the client.

Default version:

// pages/_document.tsx
import { Html, Head, Main, NextScript } from 'next/document';

export default function Document() {
  return (
    <Html lang="en">
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

The four pieces:

  • Html — the root tag, where you set the lang attribute or add classes for theming.

  • Head — for tags that should appear in every page's head: web fonts, third-party scripts, favicons. Don't put per-page <title> or meta tags here — use the next/head component inside individual pages for that.

  • Main — where Next.js mounts your _app.tsx tree.

  • NextScript — Next.js's bootstrap scripts. Required for hydration to work.

When you'd customize it:

  • Set the html lang attribute based on locale.

  • Add a custom font link or preconnect tags. (Modern projects should prefer next/font instead.)

  • CSS-in-JS server rendering — older styled-components or Emotion setups need to inject collected styles into the document head via getInitialProps.

  • Add a body class that needs to be present before hydration to avoid a flash (e.g., dark-mode setup).

  • Inject a global script tag early in the head (analytics, error tracking) — though next/script with strategy="beforeInteractive" is usually a better choice.

What you can't do here: use React state, fetch data on every request, or render content that should change per route. _document renders once on the server with a stable structure.

In the App Router, this file doesn't exist. Its job moves to app/layout.tsx, which renders <html> and <body> directly. Per-page metadata is handled by the metadata export or generateMetadata function. The split between "static document shell" and "app provider tree" disappears, which most teams find clearer.

The key insight interviewers look for: _document.js runs server-side only and is for modifying the HTML shell. Mention the CSS-in-JS use case (styled-components style extraction) — it shows advanced knowledge.

What is the _document.js file and when would you customize it? | Hiprup