Component rendering

Add browser interactivity to imported React components.

Overview

SiteX renders components statically unless an imported component uses a client directive.

Client directives only work on imported React components. Do not put them on HTML elements or components declared in the same file.

Choosing Directives

Use the least eager directive that still matches the interaction.

  1. Use client:load for controls that must be interactive as soon as possible.
  2. Use client:idle for page chrome that is already useful as static HTML, such as a sidebar or theme-aware shell.
  3. Use client:visible for below-the-fold widgets and repeated controls, such as copy buttons in long documentation pages.
  4. Use client:media for viewport-specific UI that should hydrate only when a media query matches.

client:load

Hydrates immediately.

import Search from "@/components/search"

export default function Page() {
  return <Search client:load />
}

client:only

Renders only in the browser.

import Search from "@/components/search"

export default function Page() {
  return <Search client:only />
}

client:visible

Hydrates when the component enters the viewport.

import CopyButton from "@/components/copy-button"

export default function Page() {
  return <CopyButton client:visible value="pnpm build" />
}

client:idle

Hydrates after the browser has idle time.

import Sidebar from "@/components/sidebar"

export default function Page() {
  return <Sidebar client:idle />
}

client:media

Hydrates after a media query matches.

import DesktopNav from "@/components/desktop-nav"

export default function Page() {
  return <DesktopNav client:media="(min-width: 64rem)" />
}

Boundaries

Island roots must be imported React components.

Props must be JSON-serializable data. Functions, symbols, cyclic values, and React elements cannot cross the static-to-client boundary as props.

Children are rendered as static slot HTML. If those children contain another island, it renders independently with its own client boundary.