SSR and React Server Components
Render Liquidify in server applications with narrow client boundaries.
Liquidify packages are ESM. The interactive React components and glass providers are client components, while pages, data loading, and surrounding layout can remain server-rendered.
In a Next.js App Router project, place the client directive in the smallest module that owns interaction:
// app/account/save-button.tsx
"use client"
import { Button } from "@liquidify/react"
export function SaveButton() {
return <Button onPress={() => console.log("save")}>Save</Button>
}The Server Component can render that boundary and pass serializable data into it. Do not pass callback functions, DOM nodes, or other non-serializable values across the server/client boundary.
Import @liquidify/react/styles.css from the framework's global stylesheet entry or root layout. Keep controlled values deterministic between server output and the first client render. Browser-only application behavior belongs in an effect or event handler, not at module evaluation time.
Portals and hydration
Overlay surfaces — Sheet, Dialog, Alert, ActionSheet, Popover, Tooltip, Menu, and ContextMenu — render their floating content through a portal to document.body, and only while they are open. They emit no server markup for the open state, so there is nothing to mismatch during hydration: an overlay that starts closed produces the same initial tree on the server and the client, then mounts its content on the browser once opened. Drive open from deterministic state (or leave it uncontrolled), and let the overlay's own effect own the portal — do not read document or window at module scope.
Components that generate internal ids do so with React's useId, which is stable across the server/client boundary, so associated labels and aria-* wiring hydrate without warnings.