@nibcss/runtime

The browser layer: one runtime per page, a MutationObserver, dark mode, diagnostics events and SSR collection.

2 min readv1

The runtime is the engine plus a DOM. It scans a root, writes the rules it needs into its own <style id="nib">, and keeps watching so anything added later is styled too. It is what resolves every value the build could not read.

Install#

Terminal
npm i @nibcss/runtime

Starting it#

TypeScript
import { init, getRuntime, shareRuntime, resetRuntime, NibRuntime } from "@nibcss/runtime";
import config from "@nibcss/config";

const rt = init(config);        // create, start and share — idempotent

Export

What it is

init(options?)

create, start and share the page's runtime (idempotent)

getRuntime()

the shared runtime, or null

shareRuntime(rt)

register an instance you created yourself, without starting it

resetRuntime()

forget the shared instance (tests)

NibRuntime

the class — new NibRuntime({ root, watch, gc, …config })

darkModeBootScript()

the dark-mode decision as a string, to inline in <head> before the first paint

DARK_STORAGE_KEY

"nib-dark", the key the choice is stored under

readConfigFromDocument()

the config discovery the CDN build uses

StyleSink, DarkModeController

the pieces, if you are building something unusual

An instance#

Member

What it does

start() / destroy()

scan the root and observe it / stop and remove the stylesheet

classesFor(attr)

the class string for an attribute, generating the CSS

configure(partial)

merge new config in — one token, a recipe, prefix — and re-resolve the document

flush()

apply what the observer has queued, now (tests, or after bulk DOM changes)

toggleDarkMode(), darkMode.isDark(), darkMode.enable(), darkMode.disable(), darkMode.useSystem()

the .dark class, persisted in localStorage

engine.config, engine.css(), engine.stats()

the resolved config, the CSS so far, rule and class counts

scan(root?), gc()

re-scan a subtree, collect rules no element uses any more

Construction-only options: root (default document.documentElement), watch (observe mutations — false for one-shot SSR), gc, nativeValidation (validate values with CSS.supports).

Diagnostics in the browser#

TypeScript
document.addEventListener("nib:warning", (e) => {
  console.warn(e.detail.attr, e.detail.messages, e.detail.diagnostics);
});

document also receives nib:config whenever configure() runs, with the resolved config as its detail.

Server-side rendering#

TypeScript
const rt = new NibRuntime({ ...config, root: dom.window.document, watch: false });
rt.start();
const css = rt.engine.css();

A second runtime for a widget#

TypeScript
const rt = new NibRuntime({ root: document.querySelector("#widget")!, prefix: "wgt-", watch: true });
rt.start();

Next steps#