Server rendering
The primitives render on the server. Where the browser supports
scroll-initial-target, server HTML rests at defaultIndex before any script
runs. Elsewhere a layout effect moves there before the first paint. Either
way, with one slide per snap point, there is no layout shift.
Each slide carries its starting --deck-slide-progress in the server HTML.
That is its distance in slides from the slide the deck starts at. A loop's
copy is measured by its own place in the run. Fade, curve and your own CSS on progress then paint from the
server HTML as they do once hydrated. With equal-size slides, one per snap
point, the engine's first measurement gives the same values, so hydration
changes nothing.
The server cannot measure, so it renders Prev and Next, and Dots and Counter
with one page per slide. Hydration corrects them where that is wrong. It
removes the controls when every slide fits, and recounts Dots and Counter when
several slides share a snap point or the deck snaps in pages. Where Deck.Root
cannot see the slides ahead of time, as when Deck.Viewport sits inside your
own component, Dots and Counter render empty until hydration. useDeck()
reports a count of null on the server, so a counter built on it renders
its total at hydration.
A React Server Components framework such as the Next.js App Router renders
the deck straight from a server component, effect={fade} and the theme
included. The client entries, @carouseldeck/react and its effects, start with
'use client'. Under the react-server export condition, which these
frameworks resolve for a server component, @carouseldeck/react resolves to a
server entry instead. Its Deck.Root is a server component that counts the
slides, so Dots and Counter count a page per slide there too. Every other
export is the client entry's own. A framework that does not resolve
react-server gets the client entry, and Dots and Counter render empty until
hydration.
In a server file, Deck.Root is a server component, not a client reference.
Render it there as an element. Passing it as a value to a client component,
as in as={Deck.Root}, fails. Import it in your client component instead.
Function props, such as onIndexChange and onFocalChange, and a ref to
the handle cannot cross from a server component. To use them, render the deck
from your own client component. An effect of your own crosses only from a module
that starts with 'use client'.