0.1.0-alpha.7

Dev tools

zerolith's development tools live in the page, not in a browser extension: an inspector that docks at the bottom of the page, a hook any tool can read, and timings in the browser's Performance panel. All three exist only in development builds; a production build ships none of them and records nothing.

The inspector

The inspector is a plain ES module, so it works wherever the application is served: zerolith dev, Vite, a static server, electron-vite, or file://. Mount it once, as the starter's main.ts does; in a production build the call does nothing, since the package's production entry is an empty stand-in.

import { mountDevtools } from "@zerolith/devtools";

mountDevtools();

Press Alt+Shift+Z or the launcher button to open the dock. It has three tabs:

Tab Shows
Signals Every signal, computed value, and effect, with its kind, its name, how many nodes depend on it, and its current value
Roots Every mounted root, whether render or hydrate created it, and the element it lives in
Diagnostics Every warning and error reported so far, with its severity, its cause, its arguments, and a link to its code's page

mountDevtools({ open: true }) starts with the dock open, and the handle it returns has toggle(open) and dispose(). Everything the inspector creates for itself is marked internal and left out of its own tables.

The hook

Development builds publish globalThis.__ZEROLITH_DEVTOOLS__, a small object the inspector reads. It is one consumer: a browser extension, a test, or an agent's MCP server can read the same hook.

Member Returns
version The version of the hook's shape
nodes() The live reactive nodes, oldest first: each with its id, its kind (state, computed, or effect), its name, its value, and how many observers depend on it
roots() The mounted roots, each with its id, its kind (render or hydrate), and its container
diagnostics() The most recent diagnostics, oldest first
subscribe(listener) An unsubscribe function; the listener receives each change as it happens

A subscriber hears four kinds of event: node when a reactive node is created, root when a root mounts or is removed, diagnostic with each new record, and flush with the number of effects that ran after a change.

Performance panel

In development, the runtime times its work as entries in Chrome's Performance panel, through performance.measure with the DevTools extensibility payload, so framework work is visible next to layout and paint without any extension. The entries sit in a zerolith group:

Track Entries
Render zerolith:render and zerolith:hydrate, one per root
Signals zerolith:effect, one per effect run

Each entry is cleared from the page's performance buffer as soon as it is recorded, so performance.getEntriesByType("measure") lists none of them and a long session does not accumulate them; the Performance panel keeps every one it recorded.