Server rendering & hydration

Static and dynamic styles with SSR, streaming, hydration and CMS content.

1 min readv1

Static attributes: nothing to do#

With the build plugin, static nib attributes are in the stylesheet before the HTML arrives. With rewrite: true the server HTML already carries the classes.

Dynamic values: collect and inline#

useNib (and the Vue/Svelte equivalents) generate CSS during the server render. Put it in the document so the first paint is styled; the client runtime adopts the same <style id="nib">:

TSX
const rt = new NibRuntime({ watch: false, ...config });
const app = renderToString(<NibProvider runtime={rt}><App /></NibProvider>);
const css = collectNibStyles(rt);

Streaming (Next.js App Router)#

Flush collected CSS with useServerInsertedHTML in a client component:

TSX
"use client";
import { useServerInsertedHTML } from "next/navigation";
import { collectNibStyles, useNibRuntime } from "@nibcss/react";

export function NibStreamStyles() {
  const rt = useNibRuntime();
  useServerInsertedHTML(() => <style id="nib" dangerouslySetInnerHTML={{ __html: collectNibStyles(rt) }} />);
  return null;
}

Hydration warnings#

Warning

Cause

Fix

attribute mismatch on <html class>

the runtime added dark before hydration

suppressHydrationWarning on <html>

class differs on an element

the runtime rewrote a nib attribute that React also renders

use rewrite: true, or useNib for that element

style flash on navigation

CSS for dynamic values not collected

render <NibStyles /> / collectNibStyles

Content from a CMS or database#

Markup that arrives at request time was never seen by the build. Compile it on the server with the engine and send the CSS alongside — see the Next.js guide.

Next steps#