
Custom _app and Custom _document in Next.js

Two of the most easily confused files in a traditional Next.js application are _app and _document.
They both sound central. They both sit close to the framework entry points. They both feel like places where "global" things might go. That is exactly why developers often blur their responsibilities together.
The truth is that they solve different problems.
If you understand that _app is about the React application and _document is about the surrounding HTML document, the distinction becomes much clearer.
On a larger build, that split stops being an academic distinction. On the Nando’s UK & Ireland Replatform, keeping application concerns in _app and document concerns in _document was part of staying sane as the platform grew.
_app wraps your page components
The custom App component lets you control how all page components are initialised.
At a simple level, it looks like this:
import type { AppProps } from 'next/app';const MyApp = ({ Component, pageProps }: AppProps): JSX.Element => { return <Component {...pageProps} />;};export default MyApp;Every page is rendered through this component.
That makes _app the natural place for application‑wide concerns such as:
- shared layout wrappers
- providers
- global styles
- page transition logic
_document is different
Custom _document is not for ordinary application logic. It is for controlling the overall HTML document that Next.js renders on the server.
A custom document usually looks more like this:
import Document, { Head, Html, Main, NextScript,} from 'next/document';class MyDocument extends Document { public render(): JSX.Element { return ( <Html lang="en"> <Head /> <body> <Main /> <NextScript /> </body> </Html> ); }}export default MyDocument;This file controls the outer document shell, not the internal page tree.
The Easiest Distinction
If the feature belongs to the React application users interact with after hydration, _app is probably the place.
If the feature belongs to the server‑rendered HTML document itself, _document may be the place.
That simple split prevents most confusion.
Good uses for _app
_app often becomes the home for application‑level wrappers.
For example:
- a theme provider
- a global state provider
- common layout chrome
- imported global CSS
It is also the right place when every page should share some surrounding structure:
const MyApp = ({ Component, pageProps }: AppProps): JSX.Element => { return ( <SiteLayout> <Component {...pageProps} /> </SiteLayout> );};That is a natural fit because we are still inside the React application tree.
Good uses for _document
_document is for the HTML shell around the app:
- setting the
langattribute on<html> - customising the
<body> - injecting document‑level markup the server should output
- integrating certain CSS-in-JS or SSR requirements
The important point is that this file affects the outer document structure, not the component hierarchy inside the app.
Why putting the wrong thing in _document causes confusion
Because _document is rendered on the server, it is not the place for interactive UI logic, event handlers, or application state concerns.
Developers sometimes reach for it because it feels "global", but global is too vague a category. The right question is global to what?
If it is global to the HTML document, _document may fit.
If it is global to the running React application, _app is the better home.
The Main and NextScript pieces are not optional decoration
Inside _document, these pieces are essential.
<Main /> is where the page application content is rendered.
<NextScript /> is where Next.js injects the scripts it needs.
Removing or misplacing them usually breaks the application badly. That is a useful reminder that _document is infrastructure territory, not just another component file.
_app is a better place for shared UI
Suppose every page needs:
- a header
- a footer
- analytics wrappers
- a context provider
Those belong around page rendering in _app, not in _document.
Why? Because they are part of the UI tree the React application owns and updates. They are not raw document scaffolding.
_document is more about shape than behaviour
That is another helpful way to think about it.
_document shapes the static outer HTML.
_app shapes how the application behaves and is composed.
Once you keep those two jobs separate, the files stop looking interchangeable.
Keep the Responsibilities in Their Own Lane
If a team starts placing providers, layout logic, and runtime concerns into _document, the project becomes harder to reason about because it is ignoring the separation the framework is trying to give you.
Likewise, if document‑level HTML concerns are scattered into page files instead of handled centrally where appropriate, the application becomes less consistent.
Next.js gives us these two entry points precisely so those responsibilities can stay distinct.
Not Every Project Needs Heavy Customisation
Another small but useful point: just because these files exist does not mean every project should stuff them with logic.
A custom _app can be small.
A custom _document can be minimal.
There is no point using framework extension points just because they exist. They earn their keep when there is a real cross‑cutting responsibility to express.
Separate the React App from the HTML Shell
Custom _app and _document feel confusing only when both are treated as vague "global" buckets. In reality, they are for different layers of the system. _app is about the React application and the wrappers around page components. _document is about the outer HTML document rendered on the server.
Once that distinction is clear, both files become much easier to use correctly, and the application architecture stays cleaner for it.
Related Articles

Understanding the JavaScript Event Loop. 
10 Essential SEO Tips for Front‑End Developers. 10 Essential SEO Tips for Front‑End Developers
Handling Click Events in JavaScript. Handling Click Events in JavaScript

Pass by Value vs. Reference in JavaScript. Pass by Value vs. Reference in JavaScript

Flattening Arrays in JavaScript. Flattening Arrays in JavaScript

Check If Three Values are Equal in JavaScript. Check If Three Values are Equal in JavaScript

Creating Interactive User Interfaces with HTML, CSS, and JavaScript. Creating Interactive User Interfaces with HTML, CSS, and JavaScript

Handling API Routes in Next.js: When to Use Server Actions vs. API Routes. Handling API Routes in Next.js: When to Use Server Actions vs. API Routes

Hiring a Freelance Front‑End Developer ‑ An Ultimate Guide. Hiring a Freelance Front‑End Developer ‑ An Ultimate Guide

Converting Between Camel, Snake, and Kebab Case in JavaScript. Converting Between Camel, Snake, and Kebab Case in JavaScript

Optimising Vue.js Performance with Lazy Loading and Code Splitting. Optimising Vue.js Performance with Lazy Loading and Code Splitting

Throttling vs. Debouncing in JavaScript: Managing Event Frequency. Throttling vs. Debouncing in JavaScript: Managing Event Frequency