Skip to content
uiify

Server components

Most uiify components are Server Components that ship no client JavaScript. Those that need it say so in the import path.

The root entry is a client boundary

Importing from @gunkin/uiify is convenient and marks a client boundary. In a Server Component, import the component’s own entry instead; it has no "use client" directive.

// convenient: a client boundary
import { Accordion } from "@gunkin/uiify";

// server-compatible: no client JavaScript
import { Accordion } from "@gunkin/uiify/components/accordion";

Controlled variants under /client

A controlled component always needs a client boundary, because something must hold the value and re-render. Controlled variants therefore live under a /client subpath, not behind a prop.

import { Modal } from "@gunkin/uiify/components/modal"; // uncontrolled, 0 kB
import { ModalClientContent } from "@gunkin/uiify/components/modal/client"; // controlled

The hydration cost then appears in an import you wrote, not in a later bundle report. The uncontrolled component is the one that works before hydration.

Composing across the boundary

A Client Component can render Server Components passed as children, which keeps an interactive shell thin while its content stays on the server.

// server component
<ClientShell>
  <ExpensiveServerRenderedThing />
</ClientShell>

Avoid React context

Tier 0 bans React context: Server Components cannot use context, so parts that communicate through a provider cannot render on the server. Parts are wired with HTML attributes and deterministic ids instead.

Follow the same rule when you build on @gunkin/uiify/elements: the browser resolves commandfor, popovertarget, for and name without JavaScript. See Architecture

Before hydration

Tier 0 components pass the no-JavaScript suite in full: they are operable, not only visible. Tier 1 keeps native state working and loses only what its island adds. Tier 2 renders meaningful markup; keyboard navigation, filtering and ARIA sync wait for hydration.

Each component page shows its tier and measured budget; Proof explains how both are produced.