Skip to content
Tennantite
中文
Documentation

SSR / RSC

Server-rendering constraints, use client boundaries and verification apps.

Hard constraints

  1. Server render must not throw or touch window, document or localStorage.
  2. Initial HTML must be complete; critical content cannot wait for the client.
  3. Hydration must not warn; server and client first frames must match.

packages/ui/src/ssr.test.tsx uses renderToStaticMarkup in Node to render primitives, ScreenPanel and PlayerInventory. Any browser API at module scope or during render fails the test.

use client boundaries

  • Base UI components opt into "use client" in the component or by the caller when interaction is needed.
  • useHasHover returns false on the server and reads matchMedia in an effect; hover is a desktop enhancement.
  • Do not branch markup on typeof window !== "undefined"; it produces first-frame mismatches. Put the difference in an effect or CSS.

Two-framework verification

pnpm --filter @tennantite/next-app dev
pnpm --filter @tennantite/tanstack-app dev

Next.js App Router runs on port 3100 and TanStack Start on 3200. Both render the same controls to catch framework-level prerender and hydration differences.

Automated smoke test

pnpm --filter @tennantite/ui test

The Vitest SSR test uses the Node environment, not jsdom. It proves “the server can render”, not browser interaction; interaction and accessibility are covered by the jsdom tests.

This site

This site is statically generated by Astro at build time. Documentation pages load no preview/demo React chunk; only the idle-hydrated search island and a small native copy script. Component and Block pages hydrate previews on demand.