From 18766e90713add769f7c7fe01093ab873a27c580 Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 21 Aug 2026 13:47:48 +0200 Subject: [PATCH] docs: clarify beforeInteractive placement for root layouts (#97643) Fixes: https://github.com/vercel/next.js/issues/97602 --- docs/01-app/02-guides/migrating/app-router-migration.mdx | 2 +- docs/01-app/03-api-reference/02-components/script.mdx | 8 +++++++- errors/no-before-interactive-script-outside-document.mdx | 6 +++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/01-app/02-guides/migrating/app-router-migration.mdx b/docs/01-app/02-guides/migrating/app-router-migration.mdx index ef794a34573..5cdcb9a3320 100644 --- a/docs/01-app/02-guides/migrating/app-router-migration.mdx +++ b/docs/01-app/02-guides/migrating/app-router-migration.mdx @@ -108,7 +108,7 @@ To upgrade your links to Next.js 13, you can use the [`new-link` codemod](/docs/ The behavior of [`next/script`](/docs/app/api-reference/components/script) has been updated to support both `pages` and `app`, but some changes need to be made to ensure a smooth migration: -- Move any `beforeInteractive` scripts you previously included in `_document.js` to the root layout file (`app/layout.tsx`). +- Move any `beforeInteractive` scripts you previously included in `_document.js` to a [root layout](/docs/app/api-reference/file-conventions/layout#root-layout), such as `app/layout.tsx` or `app/[locale]/layout.tsx`. - The experimental `worker` strategy does not yet work in `app` and scripts denoted with this strategy will either have to be removed or modified to use a different strategy (e.g. `lazyOnload`). - `onLoad`, `onReady`, and `onError` handlers will not work in Server Components so make sure to move them to a [Client Component](/docs/app/getting-started/server-and-client-components) or remove them altogether. diff --git a/docs/01-app/03-api-reference/02-components/script.mdx b/docs/01-app/03-api-reference/02-components/script.mdx index 432cf82941f..226031960ec 100644 --- a/docs/01-app/03-api-reference/02-components/script.mdx +++ b/docs/01-app/03-api-reference/02-components/script.mdx @@ -72,7 +72,7 @@ Scripts denoted with this strategy are preloaded and fetched before any first-pa -`beforeInteractive` scripts must be placed inside the root layout (`app/layout.tsx`) and are designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side). +Scripts with the `beforeInteractive` strategy must be placed inside a [root layout](/docs/app/api-reference/file-conventions/layout#root-layout), such as `app/layout.tsx` or `app/[locale]/layout.tsx`, and are designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side). @@ -155,6 +155,12 @@ export default function Document() { > **Good to know**: Scripts with `beforeInteractive` will always be injected inside the `head` of the HTML document regardless of where it's placed in the component. + + +> **Good to know**: These scripts run once per document load. A client-side navigation does not run them again, including one that only changes a root param, such as `/en` to `/fi`, since the root layout stays the same. + + + Some examples of scripts that should be fetched as soon as possible with `beforeInteractive` include: - Bot detectors diff --git a/errors/no-before-interactive-script-outside-document.mdx b/errors/no-before-interactive-script-outside-document.mdx index 68965e6758d..c771e50ef10 100644 --- a/errors/no-before-interactive-script-outside-document.mdx +++ b/errors/no-before-interactive-script-outside-document.mdx @@ -2,17 +2,17 @@ title: No Before Interactive Script Outside Document --- -> Prevent usage of `next/script`'s `beforeInteractive` strategy outside of `app/layout.jsx` or `pages/_document.js`. +> Prevent usage of `next/script`'s `beforeInteractive` strategy outside of a root layout or `pages/_document.js`. ## Why This Error Occurred -You cannot use the `next/script` component with the `beforeInteractive` strategy outside `app/layout.jsx` or `pages/_document.js`. That's because `beforeInteractive` strategy only works inside **`app/layout.jsx`** or **`pages/_document.js`** and is designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side). +You cannot use the `next/script` component with the `beforeInteractive` strategy outside a root layout or `pages/_document.js`. That's because `beforeInteractive` strategy only works inside a **root layout** or **`pages/_document.js`** and is designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side). ## Possible Ways to Fix It ### App Router -If you want a global script, and you are using the App Router, move the script inside `app/layout.jsx`. +If you want a global script, and you are using the App Router, move the script inside a [root layout](/docs/app/api-reference/file-conventions/layout#root-layout), any layout without a `layout.js` above it. ```jsx filename="app/layout.jsx" import Script from 'next/script'