pierre Documentation

Pierre’s open source code

5,970 stars TypeScript TypeScript 1 file Β· ~8,653 tokens #diffs#memescale#trees
RAW Doc

File: apps/docs/app/(trees)/docs/Reference/VanillaAPI/content.mdx

Vanilla API

The vanilla runtime lives at the package root, @pierre/trees.
new FileTree(...) is the runtime entry point and the imperative model surface.

Class-first story

Start with new FileTree(options). Then mount the instance.

<DocsCodeExample {...VANILLA_API_EXAMPLE} />

For shared option meanings, read
Shared concepts.

Constructor surface

new FileTree(options):

  • accepts the shared options surface
  • creates the model one time
  • expects later updates through model methods; do not rebuild option objects for
    every render

Mounting and lifecycle

render(...)

  • accepts { fileTreeContainer } when you already own the host element
  • accepts { containerWrapper } when the runtime must create and append the
    host for you

hydrate({ fileTreeContainer })

  • attaches the model to server-rendered tree markup already in the page

unmount()

  • removes the mounted runtime and keeps the model available

cleanUp()

  • final teardown: unmount, subscription cleanup, and model destruction

getFileTreeContainer()

  • returns the mounted host element after render or hydrate

Read APIs

Common read methods are:

  • getItem(path)
  • getFocusedItem()
  • getFocusedPath()
  • getFocusedIndex()
  • getVisibleCount()
  • getVisibleRows(start, end)
  • getSelectedPaths()
  • getComposition()
  • isSearchOpen()
  • getSearchValue()
  • getSearchMatchingPaths()

These reads stay path-oriented and model-oriented. They do not ask you to infer
the tree state from DOM order.

Item handles

getItem(path) returns a file handle, a directory handle, or null.

Shared handle actions:

  • getPath()
  • focus()
  • select()
  • toggleSelect()
  • deselect()

Directory-only actions:

  • expand()
  • collapse()
  • toggle()

Write and control APIs

Focus and selection control:

  • focusPath(path)
  • focusNearestPath(path | null)
  • focusFirstItem() / focusLastItem()
  • focusNextItem() / focusPreviousItem()
  • focusParentItem()
  • scrollToPath(path, { offset: 'top' | 'center' | 'nearest', focus?: boolean })
  • startRenaming(path?)
  • item-handle selection and focus methods

scrollToPath(...) scrolls the virtualizer without moving DOM focus. It updates
model focus by default. Pass focus: false to keep model focus unchanged.

The traversal methods follow the current visible tree, including its active
expansion and search state. getVisibleRows(start, end) uses inclusive row
indexes and returns path-first row metadata for building custom navigation.

Search control:

  • setSearch(value)
  • openSearch(initialValue?)
  • closeSearch()
  • focusNextSearchMatch()
  • focusPreviousSearchMatch()

Data and mutation control:

  • add(path)
  • remove(path, options?)
  • move(fromPath, toPath, options?)
  • batch(operations)
  • resetPaths(paths, options?)
  • onMutation(type, handler)

Runtime reconfiguration helpers:

  • setComposition(composition?)
  • setGitStatus(gitStatus?)
  • setIcons(icons?)

Subscriptions and external systems

Use subscribe(listener) when any tree change must refresh a derived snapshot.
Use onMutation(...) when add, remove, move, reset, or batch intent matters.

This separation keeps model subscriptions for state reads. It keeps mutation
events for semantic side effects.

Composition surface

The composition surface covers:

  • header composition
  • context-menu composition
  • runtime updates through setComposition(...)

Read
Rename, drag, and trigger item actions
for workflow-level guidance.

Hydration boundary

This page names only the vanilla hydration entry point:
hydrate({ fileTreeContainer }). The full server-preload-first contract is in
SSR API.

Appearance boundary

This page names the runtime touchpoints such as getFileTreeContainer(),
setGitStatus(...), and setIcons(...). For styling variables, theme helpers,
and unsafeCSS, read Styling and theming. For icon
remaps and icon-set lookup, read Icons.


File: apps/docs/app/(trees)/docs/Reference/StylingAndTheming/content.mdx

Styling and theming

This page is the lookup reference for host styling, CSS-variable families,
themeToTreeStyles(...), and the unsafeCSS escape hatch.

Styling entry points

Host styling comes first.

  • React: use normal host className and style props on
    <FileTree model={...} />
  • Vanilla: style the mounted host that getFileTreeContainer() returns

Host styles own width, height, borders, background, and panel placement. CSS
variables control the UI inside that host.

CSS custom property families

The tree styling surface uses variable families, not one flat list.

Core families include:

  • panel, background, and foreground tokens
  • hover, selection, and focus tokens
  • input and search tokens
  • Git-status color tokens
  • icon color tokens for supported built-in icon sets

Fallback precedence

Trees resolves styling in this order:

  1. explicit override variables such as --trees-*-override
  2. --trees-theme-* variables from theme helpers
  3. library defaults

So themeToTreeStyles(...) fills the middle layer. Direct overrides still win.

`themeToTreeStyles(...)`

themeToTreeStyles(theme) maps a VS Code or Shiki-style theme object into host
styles. It also maps the theme to the --trees-theme-* variables that the tree
understands.

Input shape:

  • TreeThemeInput
  • key fields: type, bg, fg, colors

Output shape:

  • TreeThemeStyles
  • compatible with React inline styles and vanilla host-style assignment

<DocsCodeExample {...STYLING_THEMING_REFERENCE_EXAMPLE} />

The helper covers panel colors, selection colors, focus rings, input colors, and
Git-status colors. Explicit overrides can still replace any derived token later.

Runtime touchpoints

React:

  • keep styling on the host element through normal className and style props
  • there is no separate React-only styling API beyond the shared tree options

Vanilla:

  • apply styles through the host or container that you already own
  • getFileTreeContainer() is the handoff back to application styling code

`unsafeCSS` escape hatch

unsafeCSS is the secondary path. Use it only when the supported host and
variable surfaces cannot express the customization.

Reference topics:

  • the option name and public package surface
  • shadow-root CSS injection at a high level
  • a warning that this is the exception path, not the default styling story

Keep it narrow. Do not make it a raw stylesheet-asset strategy.


File: apps/docs/app/(trees)/docs/Reference/SSRAPI/content.mdx

SSR API

The SSR entry point lives in @pierre/trees/ssr. It owns server preload and the
server-to-client handoff contract.

Server-preload-first contract

Start with the server step, not the client step. Call preloadFileTree(options)
on the server. Then pass the returned value forward as one opaque handoff
object.

<DocsCodeExample {...SSR_API_EXAMPLE} />

Hydration reuses that server work. It is not a separate rendering strategy with
a different public data model.

`preloadFileTree(...)`

preloadFileTree(...):

  • accepts the shared FileTreeOptions surface
  • pre-renders the tree for first paint
  • returns an opaque SSR payload

The current exported payload type name is FileTreeSsrPayload. But the
docs-facing rule stays the same. Pass it through unchanged.

`serializeFileTreeSsrPayload(...)`

serializeFileTreeSsrPayload(payload, mode?) turns the preloaded payload into a
full host-markup string.

Use it when your server integration needs a serialized HTML string. This avoids
a framework-specific render boundary. The payload still stays opaque at the docs
level.

Opaque payload framing

Treat the preload result as a handoff object. Do not treat it as a
field-by-field integration surface.

Docs can name the runtime touchpoints that use it:

  • React passes the payload as preloadedData
  • Vanilla hydrates the server-rendered tree already in the page with
    hydrate({ fileTreeContainer })

Do not make the raw payload fields the public story.

Handoff rules

The server and the client must use the same tree-defining options.

Match:

  • the same path source (paths, prepared input, or presorted prepared input)
  • the same id discipline
  • the same expansion and search options when they change the initial rendered
    tree
  • the same appearance options when they change the initial markup or icon output

A mismatch is not a supported partial merge. It produces a hydration mismatch or
an incorrect first state.

Prepared input and hydration

Hydration works with raw paths or prepared input. But the recommended scale
path is server-prepared input with matching client consumption.

For the shared input model behind that rule, read
Shared concepts.

React handoff

React still creates the model with useFileTree(...). Then it passes the
payload to <FileTree model={model} preloadedData={payload} />.

For the full runtime surface, read React API. For the workflow
guide, read SSR.

Vanilla handoff

Vanilla emits the server-rendered tree into the page first. Then it creates
new FileTree(options) on the client. Then it calls
fileTree.hydrate({ fileTreeContainer }) against the existing host.

For the full runtime surface, read Vanilla API. For the workflow
guide, read SSR.

Advanced note boundary

Keep any note about declarative shadow DOM or hydration warnings short and
secondary. This page owns the public handoff contract, not the DOM internals.


File: apps/docs/app/(trees)/docs/Reference/SharedConcepts/content.mdx

Shared concepts

This page owns the cross-runtime language for Trees. React, vanilla, and SSR all
use the same path-first identity model. They use the same tree-defining inputs.
They use the same mutation vocabulary.

Path-first identity

Canonical path strings are the public identity for tree items. Use paths for:

  • selection values
  • focused-item lookups
  • search matches
  • rename and drag-and-drop events
  • Git status attachment
  • row annotations

Files and directories share the same identity space. The APIs mark the item kind
when that difference matters.

Input shapes

Trees accepts three related input shapes:

  • paths: the low-ceremony path for demos, tests, and small static trees
  • preparedInput: the recommended scale-oriented input shape
  • presorted prepared input: the highest-performance prepared-input path when the
    server already knows the final order

Use prepareFileTreeInput(...) and preparePresortedFileTreeInput(...) from
@pierre/trees to create the prepared forms. Treat prepared input as an opaque
tree-input object. Do not build the shape by hand.

Shared option groups

This table lists the shared meaning of the public options surface across
runtimes.

Option Meaning Typical use
paths Raw canonical path list. Small demos, tests, very small static trees.
preparedInput Pre-shaped tree input created ahead of render. Recommended input for larger trees.
id Stable host identity for the tree. Coordinate server preload and client hydration, or set a predictable DOM id.
initialExpansion Baseline expansion policy for the first render. Start broadly open, broadly closed, or at a specific depth.
initialExpandedPaths Specific paths that should begin expanded. Keep key folders open on first render.
initialSelectedPaths Paths selected on first render. Seed selection for previews or restored state.
flattenEmptyDirectories Flattens chains of single-child directories into one visible row. Compact repo-style trees.
sort Client-side ordering for non-presorted input. Secondary path when order must be chosen in the client.
search Enables the built-in search surface and model search methods. Searchable trees.
initialSearchQuery Starting search value. Preloaded filtered views or restored search state.
fileTreeSearchMode Controls how matches change the visible tree. Choose between filtering, collapsing, or expanding around matches.
onSearchChange Callback for search-value changes. Sync surrounding controls or analytics.
onSelectionChange Callback for selection changes. Update sibling UI that tracks current selection.
dragAndDrop Enables drag and drop plus its policy hooks. Editable trees.
renaming Enables inline rename plus policy hooks. Rename-in-place workflows.
composition Header and context-menu composition surface. Add a header row or contextual commands.
gitStatus Built-in Git-style row signals. Added, modified, deleted, ignored, renamed, and untracked states.
icons Built-in icon set or icon configuration object. Set selection, color mode, remaps, or sprite-sheet extension.
renderRowDecoration Custom non-Git row signal renderer. Generated-file badges, remote markers, validation hints.
density Density preset or custom spacing factor. Tune row height and spacing in one place.
itemHeight Explicit row-height override. Row height that doesn't match a density preset.
overscan Extra rows rendered outside the visible window. Smooth scrolling tradeoffs.
initialVisibleRowCount Optional first-render row budget before the browser measures height. Tune SSR and hydration work without pinning steady-state size.
unsafeCSS Advanced CSS injection into the tree shadow root. Narrow escape hatch when supported styling surfaces are not enough.

Tree-shape options

The tree-shape options are paths, preparedInput, initialExpansion,
initialExpandedPaths, flattenEmptyDirectories, and sort.

Use them to answer three questions:

  1. where the tree data comes from
  2. what the initial visible shape must be
  3. whether the client must still shape or sort the data

For the recommended setup, read
Shape tree data for fast rendering.

Search mode semantics

Trees supports three search modes:

  • hide-non-matches: shows only the matches and the ancestor chain that keeps
    them navigable. This is the guide default.
  • collapse-non-matches: keeps the matching paths and the ancestor chain
    visible. It collapses unrelated branches out of the way.
  • expand-matches: expands the matching branches into the surrounding tree
    context. It keeps non-matching rows visible.

React and vanilla use the same search modes. Runtime pages must not redefine
them.

Selection, focus, and item handles

Selection is path-based. Focus is path-based. Item handles are path-oriented
helpers for a known item.

Common lookup topics are:

  • get an item by path
  • read the focused and selected state
  • focus, select, toggle, or deselect through the model or item handle
  • expand, collapse, or toggle directories through a directory handle

Read
Navigate selection, focus, and search
for workflows. Read React API for selector hooks. Read
Vanilla API for direct class methods.

Interaction and editing options

dragAndDrop, renaming, and composition are the runtime-agnostic editing
surfaces. They share the same path-first event model. The React and vanilla
integration points differ.

Read
Rename, drag, and trigger item actions
for the user-facing workflows that build on those options.

Appearance and annotation options

gitStatus, icons, renderRowDecoration, and unsafeCSS all affect how rows
look. But they do different jobs:

  • gitStatus is the built-in Git-style signal lane
  • icons controls icon sets, remaps, and sprite-sheet extension
  • renderRowDecoration adds non-Git row metadata
  • unsafeCSS is the narrow fallback when public styling surfaces are not enough

For deeper lookup, read Styling and theming and
Icons.

Scale and rendering settings

initialVisibleRowCount, density, itemHeight, and overscan are rendering
knobs, not onboarding concepts. The rendered container sets the steady-state
height. These options only tune the first-render budget, the visual density, and
the virtualized row window.

For density, use the density keyword ('compact' | 'default' | 'relaxed') or
a numeric factor. It sets both the row height and the spacing in one place. The
React <FileTree> wrapper paints --trees-item-height and
--trees-density-override for you. Use itemHeight only when you need a row
height that does not match a preset.

Read Handle large trees efficiently when
scale becomes the real problem.

Mutation vocabulary

Trees exposes semantic tree mutations, not DOM events. The shared mutation terms
are:

  • add
  • remove
  • move
  • batch
  • resetPaths
  • onMutation

Mutation payloads stay path-first. Reset events also report whether prepared
input was involved. Invalidation metadata reports whether the canonical state or
the projected visible state changed.

Use these events to sync adjacent UI, analytics, or persistence layers. Do not
turn them into a filesystem-sync tutorial.

Opaque SSR payload framing

Server preload returns one handoff object. Pass it forward unchanged.

React uses that handoff as preloadedData. Vanilla hydrates existing server
markup through hydrate({ fileTreeContainer }). Neither runtime must teach the
field-by-field payload steps as the main story.

For the preload and hydration contract, read SSR API.


File: apps/docs/app/(trees)/docs/Reference/ReactAPI/content.mdx

React API

The React entry point lives in @pierre/trees/react. It is a thin React
integration layer over the same imperative model that the vanilla runtime uses.

React model-first story

Start with useFileTree(options). Do not build a large controlled component.
The hook creates one stable model for the component lifetime. Later option
changes do not reconfigure the model. Update the model through model methods
instead.

<DocsCodeExample {...REACT_API_EXAMPLE} />

For the shared option meanings behind that call, read
Shared concepts.

`useFileTree(...)`

useFileTree(...):

  • accepts the shared tree-options surface
  • creates the model one time
  • cleans up the model when the React component unmounts
  • returns UseFileTreeResult, which currently exposes model

Use model methods when the tree changes after mount. The methods include
resetPaths(...), setComposition(...), setGitStatus(...), setIcons(...),
and the search or mutation methods.

``

The React component mounts the model into a host element.

Primary props:

  • model
  • normal host HTML attributes such as className, style, and id

React-only props:

  • header
  • renderContextMenu
  • preloadedData

Behavior notes:

  • it renders the model into the host element
  • it hydrates instead of rendering fresh when matching preloaded content is
    already present
  • it uses id ?? preloadedData?.id for host identity during hydration
  • header and renderContextMenu add React rendering onto the model
    composition surface

Reading tree state from React

React components read from the model through selector hooks. React components
write back through model methods.

Common read patterns include:

  • selected paths for sibling panels or action bars
  • search state for search inputs and result counts
  • custom derived snapshots such as "is this path focused?"

Selector hooks

useFileTreeSelector(model, selector, equality?)

  • generic bridge from the imperative model into React
  • returns a selected snapshot from the current model
  • accepts an optional equality function when the selected value needs custom
    comparison

useFileTreeSelection(model)

  • convenience hook for readonly string[] selected paths

useFileTreeSearch(model)

  • returns the current search snapshot and the model-backed actions
  • snapshot fields: isOpen, matchingPaths, value
  • actions: open(initialValue?), close(), setValue(value),
    focusNextMatch(), focusPreviousMatch()

<DocsCodeExample {...REACT_API_SELECTOR_HOOKS} />

Writing to the model from React

React writes through the same imperative model methods that the vanilla runtime
exposes.

Typical write paths are:

  • focus and selection methods on the model or item handles. This includes
    scrollToPath(...), which reveals a path without moving DOM focus and makes
    optional model focus changes.
  • visible-tree traversal through focusFirstItem(), focusLastItem(),
    focusNextItem(), focusPreviousItem(), and focusParentItem().
  • visible row inspection through getFocusedIndex(), getVisibleCount(), and
    getVisibleRows(start, end) when surrounding UI needs custom navigation.
  • search methods such as setSearch(...) and openSearch(...)
  • mutation methods such as add(...), remove(...), move(...), batch(...),
    and resetPaths(...)
  • runtime reconfiguration methods such as setComposition(...),
    setGitStatus(...), and setIcons(...)

React-specific composition surface

React adds two high-level composition props on top of the model:

  • header for React-rendered header content
  • renderContextMenu(item, context) for React-rendered context menus

Use them when the menu or header belongs in React. The shared meaning of the
composition options is in
Shared concepts.

Mutation and subscriptions from React

Use selector hooks when React UI needs reactive reads. Use
model.onMutation(...) when you need semantic side effects. Examples are
persistence, logging, or analytics around add, remove, move, reset, or batch
operations.

Hydration boundary

The React runtime uses server preload through preloadedData on <FileTree />.
The model still comes from useFileTree(...). The client must use matching
tree-defining options.

For the preload contract, read SSR API. For workflow guidance, read
SSR.

Appearance boundary

Style the React host with normal host props such as className and style. For
deeper lookup, read Styling and theming and
Icons.


File: apps/docs/app/(trees)/docs/Reference/Icons/content.mdx

Icons

This page is the lookup reference for icon sets, icon remaps, sprite-sheet
extension, and icon-specific configuration rules.

Entry points

Built-in set selection:

  • icons: 'minimal' | 'standard' | 'complete'
  • minimal keeps the visual noise low
  • standard adds common language and file-type icons
  • complete has the broadest built-in coverage

Object configuration:

  • use FileTreeIconConfig when a string set is not enough
  • combine a base set with color toggles, slot remaps, or file-specific remaps

Configuration shape

Base set and color mode:

  • set?: 'minimal' | 'standard' | 'complete' | 'none'
  • colored?: boolean

set: 'none' turns off the built-in file-type mappings. File rows still fall
back to the generic file icon. Remaps can replace that icon.

Sprite-sheet extension:

  • spriteSheet?: string
  • supply an SVG string with <symbol> definitions that remaps can target

Built-in slot remapping:

  • remap?: Record<string, RemappedIcon>
  • common slots: chevron, generic file icon, modified-state dot, locked-path icon

File-specific remapping:

  • byFileName for exact basename matches such as package.json
  • byFileNameContains for basename substring rules such as dockerfile
  • byFileExtension for extension rules without a leading dot, and for
    multi-part suffixes such as spec.ts

Resolution order

File icon lookup resolves in this order:

  1. exact basename match from byFileName
  2. basename-contains match from byFileNameContains
  3. extension match from byFileExtension, and the more specific suffix wins
  4. built-in set mapping
  5. generic file-slot remap or fallback

So spec.ts wins over ts when both rules exist.

`RemappedIcon` shape

RemappedIcon supports two forms:

  • a string symbol id
  • an object with name, and optional width, height, and viewBox

Use the object form when the replacement symbol needs non-default geometry
metadata.

Runtime touchpoints

React:

  • pass the icon configuration through the model options for useFileTree(...)

Vanilla:

  • pass the icon configuration at construction time
  • update it later with setIcons(...)

For the runtime-specific lookup around those touchpoints, read
React API and Vanilla API.

Icon color interplay

Turn off the built-in colored icons with colored: false. The token lookup and
the fallback precedence for icon colors are in
Styling and theming.


File: apps/docs/app/(trees)/docs/Overview/content.mdx

Overview

**Trees is in beta.** Start from the public React, vanilla, and SSR entry points on this page. Expect refinements and small API changes between beta releases.

Trees uses one path-first model. The model works the same across React,
vanilla, and SSR hydration. Selection, focus, search, rename, drag and drop, Git
status, and row annotations all use canonical paths.

These docs are guide-first. First, select your runtime. Next, shape the tree
data before it reaches the UI. Then add search, item actions, styling, icons,
row signals, or SSR when you need them.


File: apps/docs/app/(trees)/docs/Guides/StyleAndThemeTheTree/content.mdx

Style and theme the tree

Start with the host element. Then move inward. Host styles control the outer
panel. CSS variables control most of the tree appearance.
themeToTreeStyles(...) maps an editor-like theme into the same variable
system. unsafeCSS is the escape hatch when the supported surfaces cannot reach
a narrow case.

Start with host styling

The host element is the outer panel boundary. Use it for width, height, borders,
radius, background, and layout placement.

In React, pass normal host props to <FileTree model={...} />.

<DocsCodeExample {...STYLE_THEME_HOST_STYLING} />

In vanilla, style the mounted host element that you already own. After mount,
getFileTreeContainer() returns that element when runtime code must update it.

Use CSS variables for most visual changes

CSS variables are the main public styling surface inside the shadow root. Use
them before you inject custom CSS.

<DocsCodeExample {...STYLE_THEME_CSS_VARIABLES} />

This approach keeps the normal fallback chain in place:

  1. explicit override variables
  2. --trees-theme-* variables from theme helpers
  3. library defaults

For the token families behind those variables, read
Styling and theming.

Match an editor palette with `themeToTreeStyles(...)`

Use themeToTreeStyles(...) when your app already has a VS Code or Shiki-style
theme object. It maps that theme to host styles. It also maps the theme to the
--trees-theme-* variables that the tree understands.

<DocsCodeExample {...STYLE_THEME_TO_TREE_STYLES} />

This helper gives you matching panel colors, selection colors, search-field
colors, and Git-status colors. You do not rebuild the theme system by hand.

Set density with `density`

Pass density to useFileTree, preloadFileTree, or the vanilla FileTree
constructor. This option sets row height and spacing together. The keyword form
('compact', 'default', 'relaxed') sets both values at once. The numeric
form keeps the default row height and sets a custom spacing factor. Every
runtime paints --trees-item-height and --trees-density-override onto the
host from the resolved density. The runtimes are vanilla CSR, vanilla SSR, React
CSR, and React SSR. This step keeps the virtualized row height and the painted
row height aligned. Caller-set inline values on the host still win. So you can
override either variable directly for a one-off. Set itemHeight only when you
need a row height that does not match a preset.

The keyword presets are exported as FILE_TREE_DENSITY_PRESETS. So SSR helpers
such as initialVisibleRowCount can divide by the preset row height. They do
not hard-code it.

Choose the right styling layer

Use:

  • host styles for layout and panel framing
  • CSS variables for product-specific appearance changes inside the tree
  • themeToTreeStyles(...) when the tree must inherit an editor palette
  • getFileTreeContainer() in vanilla when runtime code needs the mounted host
    element

Add explicit overrides on top when the imported theme is close but not final.

`unsafeCSS` is the escape hatch

Use unsafeCSS for cases that the supported host and variable surfaces cannot
express. Keep it small, local, and secondary.

<DocsCodeExample {...STYLE_THEME_UNSAFE_CSS} />

Do not start here. Do not rebuild the whole visual system from raw selectors.
For a broad lookup of the supported styling surfaces, read
Styling and theming. For icon-specific appearance
changes, continue with Customize icons.


File: apps/docs/app/(trees)/docs/Guides/SSR/content.mdx

SSR

Use SSR when the tree must arrive from the server with a fast first paint. The
tree then becomes interactive on the client. SSR is not a third primary runtime.
It is a preload-and-hydrate layer over the same React or vanilla model.

Start with the server step

Import the preload helpers from @pierre/trees/ssr. Call preloadFileTree(...)
on the server. Treat the result as one opaque handoff object.

<DocsCodeExample {...SSR_GUIDE_PRELOAD_FILE_TREE} />

The rendered container still sets the steady-state height.
initialVisibleRowCount is only a first-render hint for SSR and hydration. The
browser then measures the real viewport.

Do not unpack the payload field by field in application code. Pass it forward
unchanged.

Core invariants

The server and the client must use the same tree-defining options. Match the
same input source. Match the same id discipline. Match the same
state-affecting options that change the first rendered tree.

The result is a hydration mismatch when the server preloads one tree and the
client builds a different one.

React flow

React still creates the model with useFileTree(...). The one difference is
that the wrapper receives the opaque handoff object as preloadedData.

<DocsCodeExample {...SSR_GUIDE_REACT_HYDRATION} />

The model stays primary. preloadedData only starts hydration.

Vanilla flow

Vanilla uses the same preload step. But the client hydrates the server-rendered
container that is already in the page.

<DocsCodeExample {...SSR_GUIDE_VANILLA_HYDRATION} />

Render normally instead of hydrating when that server-rendered container is
missing.

Keep the payload opaque

In docs and application code, call the preload result an SSR payload or handoff
object. React uses it as preloadedData. Vanilla hydrates existing server
markup. Both flows reuse the same server work. Neither flow teaches the payload
internals as the main story.

Pair SSR with prepared input for large trees

Large-tree SSR works best when the server already owns the expensive shape work.
Prepare or presort the input on the server. Preload one time. Then let the
client hydrate that same result.

Advanced note: declarative shadow DOM

The preloaded path uses declarative shadow DOM. In React, the packaged wrapper
handles the host ownership details that it needs for hydration. Use the runtime
behavior. Do not write custom DOM diffing or raw payload plumbing.

For the API-level handoff contract, read SSR API.