Server and client
Why a renderer ships no JavaScript and interactivity is relocated into a separate, explicitly marked file.
What it is
Section titled “What it is”A section’s renderer is server-rendered: it produces markup and ships no JavaScript
of its own. Anything that needs a browser — state, an event handler, a piece of a
third-party client library — is not written inside the renderer at all. It is
written as a separate, ordinary React component marked "use client" and mounted
from the renderer as an island. See Islands for how to write
one.
Why it works this way
Section titled “Why it works this way”The pipeline establishes that your code runs at exactly two moments: once when a deliverable is published, and repeatedly, behind the editor, while a user edits. Neither of those moments happens in a browser — the editor injects server-produced HTML into an iframe rather than loading a renderer bundle of its own. Three consequences follow from that, in order:
- A published page is rendered once and served as static files. A renderer that reached for a clock, a random number, or a browser global could not be rendered at publish time at all — there is no browser present to answer it, and no request in flight to answer it differently next time.
- The editor re-renders your component repeatedly while a user edits, against content that keeps changing under it. A renderer with side effects would misbehave every time that happened, not just once — the same problem the first consequence names, recurring on a shorter clock.
- An island’s props are embedded in the HTML the server produced, then read back
out of that markup in the browser. They cross the server-to-client boundary as
data, not as live references — which is why they must be JSON-serializable
(see
serializable-island-props), and why there is exactly one React instance on the page: the renderer’s output and the island’s hydration target are the same markup, not two trees reconciled against each other.
How it works
Section titled “How it works”The "use client" directive is per file, not per component tree, so the boundary
between the two worlds is a file boundary you draw yourself. Everything in a file
without the directive runs only where the page is built — the platform’s server at
publish, and again behind the editor when it re-renders your section. Everything in
a file marked "use client" also runs in the browser, hydrated in place once the
server-rendered markup carrying it has loaded. Splitting a section along that
boundary is what lets the renderer stay a pure function of its props: state,
effects, and event handlers all move to the island side of the file boundary and
never appear on the renderer side.
server-vs-client is the rule that draws this line
in practice — what the directive scopes, and which other rules stop at it.
no-client-runtime-in-server is the one
that enforces it directly: no useEffect, no fetch, no other browser-only hook or
global, and no event-handler prop, in a file on the renderer side of that boundary.
What it is not
Section titled “What it is not”Not React Server Components as a Next.js reader knows them. There is no per-request rendering here — a deliverable renders once, at publish, not on each visitor’s request — and no data fetching happens inside a renderer. A section’s content arrives already decided, on its props, from the fill stage described in The pipeline.
Not a restriction on what a section may do. Interactivity is relocated, not banned — a filter, a slider, a lightbox are all ordinary things to build, just in their own file, on the other side of the line the renderer draws.
Where next
Section titled “Where next”- Islands — writing an island, its props contract, and its editor options.
server-vs-client— what the"use client"directive scopes.serializable-island-props— the JSON-serializability rule that follows from props crossing as data.no-client-runtime-in-server— the rule that keeps a renderer free of browser-only code.- The marker contract — how the editor finds its way back from rendered markup to the schema key that produced it.