A pipeline: your layout.js source becomes a server-rendered React tree, then HTML, then a Flight payload, then browser hydration / reconciliation. The anchor throughout is your exact output, not a generic example.
Your layout is converted into plain HTML and forgotten. Next produces two coordinated outputs: visible HTML for the first paint, and an embedded React / Flight model so the browser knows what React tree that HTML represents.
Your pasted source/output is the classic Next App Router initial page response: the visible HTML is only one half of the result; the many self.__next_f.push(...) scripts are the embedded React Server Components / Flight payload that lets the browser reconstruct the React tree behind that HTML.
At first principles level, your app/layout.js is compiled, called as a Server Component, and its returned React element tree is rendered into two things that ship in a single HTML response.
RootLayout is not an HTML templatefunction RootLayout({ children }) { console.log('layout rendered') return ( <html lang="en"> <body> {children} <footer> <p>Page rendered on {new Date().toLocaleString()}</p> </footer> </body> </html> ) }
This does not mean: “Next copies this JSX into an HTML file.” It means: “Next will call this function during rendering, and the return value becomes part of a React tree.”
In the App Router, app/layout.js is a special file. The top-most one is the root layout, and it must define the document-level <html> and <body> tags. Because you did not put "use client" at the top, this layout is a Server Component by default — layouts and pages render on the server, can be streamed, and only need Client Components when you require browser APIs, event handlers, state, effects, and so on.
In your pasted HTML, that is why the final page contains:
Page rendered on <!-- -->6/22/2026, 9:53:29 PM
The <!-- --> is a React server-rendering text separator. It helps React preserve exact text-node boundaries when reconciling the server-rendered DOM.
Your files roughly imply this route tree. Next reads the folder structure as routing information.
src/app ├─ layout.js ← RootLayout ├─ styles.css ← imported by RootLayout └─ page.js ← Home page for /
URL / └─ root segment "" ├─ layout: RootLayout └─ page: Home
So your final React tree is not just RootLayout. It is closer to:
RootLayout └─ children slot └─ LayoutRouter └─ Home page
That is why your output contains internal references like the following — these are not components you wrote. They are App Router infrastructure that Next inserts around your route so it can support nested layouts, templates, loading states, errors, not-found pages, metadata, streaming, and client-side navigation.
layout-router.js
render-from-template-context.js
error-boundary.js
not-found-boundary.js
metadata-boundary.js
{children} becomes the rendered pageYour layout says <body> {children} <footer>...</footer> </body>, and your page likely returns something like <main><h1>Hello Next!</h1></main>. So the render tree becomes:
<html lang="en"> └─ <body> ├─ <main> │ └─ <h1>Hello Next!</h1> └─ <footer> └─ <p>Page rendered on 6/22/2026, 9:53:29 PM</p>
Which is exactly why the visible HTML becomes:
<body> <main> <h1>Hello Next!</h1> </main> <footer> <p> Page rendered on <!-- -->6/22/2026, 9:53:29 PM </p> </footer> ... </body>
So the direct transformation is:
RootLayout({ children: <Home /> }) ↓ <html> <body> <Home /> <footer /> </body> </html> ↓ <html> <body> <main><h1>Hello Next!</h1></main> <footer>...</footer> </body> </html>
<head> if you did not write one?Your source only wrote <html lang="en"><body>...</body></html>. But your output has a head you never authored:
<head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> ... </head>
That comes from Next’s document/metadata system. In the App Router, metadata is resolved on the server so it can be included in the initial HTML response. Even when you do not explicitly export custom metadata, Next still emits essential defaults like charset and viewport. The metadata system is why your Flight payload includes entries such as:
MetadataBoundary
ViewportBoundary
__next_metadata_boundary__
__next_viewport_boundary__
So mentally — your layout is wrapped by Next’s full document shell:
Your layout: <html> <body>...</body> </html> Next document shell: <!doctype html> <html> <head> metadata CSS links preload hints framework scripts </head> <body> rendered app Flight payload </body> </html>
<link> tag?You wrote import "./styles.css"; Next sees that import in the root layout and treats it as a global app-level stylesheet — global CSS can be imported from the root layout to apply styles across routes.
import "./styles.css";
<link
rel="stylesheet"
href="/_next/static/css/app/layout.css?v=1782158009762"
data-precedence="next_static/css/app/layout.css"
/>
That means:
styles.css ↓ bundled/extracted by Next /_next/static/css/app/layout.css ↓ linked in <head> browser downloads CSS as a normal stylesheet
The ?v=1782158009762 part is a development-mode cache-busting timestamp. It helps the browser get the newest stylesheet during dev.
Your output has the following — these are not from your layout. They are the Next / React client runtime.
<link rel="preload" as="script" href="/_next/static/chunks/webpack.js?v=..." /> <script src="/_next/static/chunks/main-app.js?v=..." async=""></script> <script src="/_next/static/chunks/app-pages-internals.js" async=""></script> <script src="/_next/static/chunks/polyfills.js" nomodule=""></script>
webpack.js module loader/runtime in dev main-app.js App Router client bootstrap app-pages-internals.js internal client components used by the router: LayoutRouter, ErrorBoundary, NotFoundBoundary, etc. polyfills.js fallback support for older browsers
Even though your own RootLayout is a Server Component, the browser still needs some JavaScript so Next can hydrate Client Components, manage the App Router, process future navigations, and interpret the embedded RSC payload.
self.__next_f.push(...) scripts?These are the embedded React Server Components payload, often called the Flight payload.
On the server, Server Components render into a special RSC payload, and that payload plus Client Component instructions are used to prerender HTML. On the first client load: HTML gives the immediate non-interactive preview, the RSC payload reconciles the Server and Client Component trees, and JavaScript hydrates Client Components.
So your response is not just HTML. It is:
HTML shell + RSC/Flight payload + router bootstrap data + client runtime scripts
“What should the browser paint immediately?”
“What React tree produced this HTML, and how should the App Router continue from here?”
That is why you see this — it initializes the client-side Flight buffer:
<script> (self.__next_f = self.__next_f || []).push([0]); </script>
Then you see many chunks like this — they stream pieces of the rendered React model into the browser:
<script> self.__next_f.push([1, '...serialized React model...']); </script>
On initial load the component payload arrives embedded in the HTML stream; later navigations can fetch only the RSC payload without a full HTML document.
8:{"name":"RootLayout","env":"Server", ...}
means React recorded that a Server Component named RootLayout was rendered.
5:["$","html",null,{ "lang":"en", "children":["$","body",null,{...}] }]
In human terms:
5:
React element:
type: "html"
props:
lang: "en"
children:
React element:
type: "body"
children:
- LayoutRouter / children slot
- footer
c:{"name":"Home","env":"Server", ...}
means your Home page component was also rendered on the server.
b:["$","main",null,{ "children":["$","h1",null,{"children":"Hello Next!"}] }]
is your page output:
<main> <h1>Hello Next!</h1> </main>
6:I["...layout-router.js",["app-pages-internals","static/chunks/app-pages-internals.js"],""]
means:
ID 6 refers to an importable client module:
Next's LayoutRouter
found in app-pages-internals.js
3:HL["/_next/static/css/app/layout.css?v=1782158009762","style"]
is a resource hint / preload-style instruction for your layout CSS.
1c:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] 1a:[["$","meta","0",{"charSet":"utf-8"}]]
corresponds to the metadata that eventually appears in the <head>:
<meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
The exact wire tokens like I, HL, D, $L6, $Y, $E(...) are React/Next implementation details, not public API. But conceptually they mean:
Do not build application logic around those exact tokens. They can change between React/Next versions.
You see things like the following — because your app is not rendered as only RootLayout → Page. It is rendered inside Next’s App Router machinery.
NotFoundBoundary
OutletBoundary
MetadataBoundary
ViewportBoundary
GlobalError
ClientPageRoot
ClientSegmentRoot
App Router request for /
└─ Root layout
└─ Router slot: children
├─ error boundary
├─ not-found boundary
├─ metadata boundary
├─ viewport boundary
├─ template context
└─ page segment
So your real server render is closer to this. You only authored the clean part; Next wraps it in the machinery required to make nested routing, streaming, errors, metadata, prefetching, and client navigation work.
<Request /> ↓ <AppRouterServerRender> ↓ <RootLayout> <body> <LayoutRouter parallelRouterKey="children"> <TemplateContext> <ErrorBoundary> <NotFoundBoundary> <MetadataBoundary> <Home /> </MetadataBoundary> </NotFoundBoundary> </ErrorBoundary> </TemplateContext> </LayoutRouter> <footer /> </body> </RootLayout>
RootLayout Home styles.css
Your RootLayout becomes the final HTML because Next calls it as a Server Component and turns its returned React element tree into server-rendered markup. But Next also embeds the Flight/RSC payload because HTML alone is not enough for the App Router — the browser also needs the serialized React tree, router state, module references, metadata boundaries, and Client Component references so React can reconcile the page and Next can perform client-side navigation.
So this:
<html lang="en"> <body> {children} <footer>...</footer> </body> </html>
becomes two things:
<html> <body> <main>Hello Next!</main> <footer>Page rendered on ...</footer> </body> </html>
self.__next_f.push(...) self.__next_f.push(...) self.__next_f.push(...)
self.__next_f.push(...) — what is each part?That line is ordinary browser JavaScript first, and only then a Next.js-specific convention. The confusing part is that Next hides a streaming protocol inside something that looks like a normal array operation.
<script> (self.__next_f = self.__next_f || []).push([0]); </script>
self?In a browser page, self is a reference to the global browser object. In normal page JavaScript:
self === window // true self === globalThis // true, in the browser main thread
So these are basically equivalent in this context:
self.__next_f window.__next_f globalThis.__next_f
Think of self as the top-level browser world where page-wide globals live. So self.__next_f means window.__next_f — in plain English: “Store this thing on the global browser object so different scripts can access it.”
__next_f?__next_f is not a JavaScript built-in. It is a custom global property created by Next.js. The name roughly means:
__next_f
│ │
│ └─ probably "Flight"
└──────── internal Next.js thing
React Server Components use a transport format often called Flight. Next embeds chunks of that Flight payload into the HTML using this global array. So self.__next_f means the place where Next stores incoming Flight/RSC chunks. A simplified mental model — it is basically a mailbox:
self.__next_f = [ [0], [1, "some serialized React Server Component data"], [1, "more serialized React Server Component data"], [1, "more serialized React Server Component data"] ]
Server ↓ <script>self.__next_f.push(...)</script> ↓ Browser global queue ↓ Next client runtime reads the queue ↓ React reconstructs/reconciles the app tree
push?push is the normal JavaScript array method. Example:
const messages = [] messages.push("hello") messages.push("world") console.log(messages) // → ["hello", "world"]
So self.__next_f.push([1, "some payload"]) means append this Flight chunk to the __next_f array. In ordinary JavaScript terms, self.__next_f.push([0]) adds the item [0] to the end of the array self.__next_f.
This line does two jobs: (1) make sure self.__next_f exists, and (2) push the first chunk into it.
(self.__next_f = self.__next_f || []).push([0]);
if (!self.__next_f) { self.__next_f = [] } self.__next_f.push([0])
The parentheses matter: (self.__next_f = self.__next_f || []) returns the array; then .push([0]) pushes into that array. In words: “Use the existing Next Flight array if it already exists. If it does not exist, create an empty array. Then push [0] into it.”
const __next_f = []?Because each inline <script> tag is separate. Your HTML has many chunks like this — and each script needs access to the same shared place:
<script> (self.__next_f = self.__next_f || []).push([0]); </script> <script> self.__next_f.push([1, "...first Flight chunk..."]); </script> <script> self.__next_f.push([1, "...second Flight chunk..."]); </script> <script> self.__next_f.push([1, "...third Flight chunk..."]); </script>
So Next puts the shared place on the global object. That way, every script tag can say self.__next_f.push(...) and they are all pushing into the same queue.
window / self └─ __next_f ├─ chunk 0 ├─ chunk 1 ├─ chunk 2 └─ chunk 3
Because the HTML response is streamed. The browser can start receiving and parsing the page before the whole response is complete. So Next can send the page in pieces, and the inline scripts act like little delivery packets:
HTML shell ↓ visible page markup ↓ Flight chunk ↓ more HTML ↓ Flight chunk ↓ more Flight chunks
Incoming HTML stream
│
▼
Browser parser
│
├─ sees <main><h1>Hello Next!</h1></main>
│ ↓
│ paints visible page
│
├─ sees <script>self.__next_f.push(...)</script>
│ ↓
│ executes script immediately
│ ↓
│ stores Flight chunk in __next_f
│
└─ continues parsing
As soon as the browser reaches one, it runs it and stores the chunk. So the browser does not need to wait for one giant JSON file at the end.
At first, self.__next_f behaves like a normal array. But when Next’s client runtime loads, it reads that array. Conceptually:
for (const chunk of self.__next_f) { processFlightChunk(chunk) }
Then Next can continue processing later chunks as they arrive. So the real mental model is:
__next_f is a buffer.
__next_f becomes a delivery channel.
Meaning: early chunks are stored, later chunks are consumed/processed.
self.__next_f.push(...)In your HTML, Next uses this pattern many times to stream React/Flight chunks into the browser. Here it is from ten angles.
self.__next_f.push(chunk) │ │ │ │ │ └─ put this item at the end of the queue │ │ │ └────────── Next.js Flight queue │ └─────────────── browser global object
In plain English: “On the browser's global object, find Next's Flight queue, then append this new Flight chunk.”
In the browser, self === window. So self.__next_f is basically window.__next_f.
Browser tab └─ Global object ├─ window ├─ self ├─ document ├─ location ├─ console └─ __next_f ← Next adds this
So self is not special to Next — self is the browser-wide object. __next_f is the special Next.js part.
__next_f looks likeself.__next_f = []
self.__next_f.push([0]) self.__next_f.push([1, "...Flight data..."]) self.__next_f.push([1, "...more Flight data..."])
self / window └─ __next_f ├─ [0] ├─ [1, "RootLayout model..."] ├─ [1, "Home page model..."] ├─ [1, "metadata model..."] └─ [1, "router state..."]
__next_f is a global queue.
Does self.__next_f already exist? │ ├─ No │ ↓ │ create [] │ └─ Yes ↓ reuse it Then: push [0] into it
So this line is an initialization + first push: create the mailbox if needed, then drop the first message into it.
Next server │ ├─ sends document shell │ ├─ sends visible HTML │ ├─ sends script: self.__next_f.push(...) │ ├─ sends more HTML │ ├─ sends another script: self.__next_f.push(...) │ └─ sends more Flight chunks
Incoming HTML stream
│
▼
Browser parser
│
├─ sees <main><h1>Hello Next!</h1></main>
│ ↓
│ paints visible page
│
├─ sees <script>self.__next_f.push(...)</script>
│ ↓
│ executes script immediately
│ ↓
│ stores Flight chunk in __next_f
│
└─ continues parsing
Your page response has two coordinated layers:
What the browser paints immediately
What React/Next uses to understand the app tree
Next server renders:
RootLayout + Page
│
▼
Produces two outputs
│
├─────────────────────────────┐
▼ ▼
Visible HTML Flight / RSC data
for the browser for React/Next
│ │
▼ ▼
<main>Hello Next!</main> self.__next_f.push(...)
<footer>...</footer> self.__next_f.push(...)
│ │
└──────────────┬──────────────┘
▼
Same HTTP response
▼
Browser receives
self.__next_f is a mailbox.
Server keeps inserting letters:
letter 1: "start Flight stream"
letter 2: "RootLayout rendered like this"
letter 3: "Home rendered like this"
letter 4: "CSS resource is here"
letter 5: "metadata is this"
letter 6: "router state is this"
Next client runtime later opens the mailbox
and reads the letters.
Server │ │ writes chunks into inline scripts ▼ <script>self.__next_f.push(chunk)</script> │ │ browser executes scripts ▼ window / self └─ __next_f ├─ chunk ├─ chunk ├─ chunk └─ chunk │ │ Next client runtime reads these ▼ React / Next app state
self.__next_f
└─ behaves like a normal array buffer
├─ push chunk
├─ push chunk
└─ push chunk
Next runtime └─ reads self.__next_f ├─ process old chunks ├─ listen for new chunks └─ connect Flight data to React
“Store chunks until Next is ready.”
“Deliver chunks to the Next runtime.”
HTML gives the browser something to paint. __next_f gives React/Next the serialized app model needed to continue, reconcile, hydrate, and navigate.