DevTools API

DevTools has two halves. The bridge lives in @quantajs/core and collects the data; the UI lives in @quantajs/devtools and renders it. You need both, and the bridge is off until you turn it on.

import { enableDevTools, disableDevTools, devtools } from '@quantajs/core';
import { mountDevTools, DevTools } from '@quantajs/devtools';

enableDevTools(options?)

Attaches the bridge and starts collecting. Until this is called, nothing is collected and nothing is attached to window.

function enableDevTools(options?: DevToolsOptions): void;

interface DevToolsOptions {
  /** Property paths to redact from emitted events, e.g. ['token', 'user.ssn']. */
  redact?: string[];
}

Redaction applies to the state and getter values the panel shows, to keys nested inside a changed value, and to action arguments that are objects carrying a matching key. Matches become [redacted].

if (process.env.NODE_ENV === 'development') {
  enableDevTools({ redact: ['token', 'user.ssn'] });
}

Note:

This is a security boundary. DevTools observes full store contents and every argument to every action, which routinely includes credentials and personal data. Before 2.1 the bridge enabled itself whenever process.env.NODE_ENV was not statically replaced — true for CDN bundles, Deno and plain <script type="module"> — leaving it on in production. Guard the call and keep it out of production builds.

Stores created before it is enabled are registered too.

disableDevTools()

function disableDevTools(): void;

Detaches the bridge and stops collecting.

devtools

The bridge object itself, for building a custom DevTools UI. devtools.enabled reports whether collection is on, and devtools.snapshot(name) returns a plain copy of a store's state and getter values with redact applied — render that, not the live store. Most applications never touch this.

@quantajs/devtools exports

  • mountDevTools(options?)
  • DevTools (Preact component)

mountDevTools(options?)

Mounts Quanta DevTools and returns a cleanup function.

Signature

function mountDevTools(options?: DevToolsOptions): () => void;

Mount options

interface DevToolsOptions {
  visible?: boolean;
  target?: HTMLElement | string;
  onError?: (error: Error) => void;
}

Note:

This is a different type from core's DevToolsOptions above, despite the shared name. visible controls whether the panel renders; it has no effect on whether data is collected. That is enableDevTools().

Option Details

  • visible
    • undefined (default): auto-detect development mode
    • true: force visible
    • false: no-op mount
  • target
    • default is 'body'
    • supports CSS selector string or HTMLElement
  • onError
    • optional callback for non-fatal mount issues (for example, missing target)

Return Value

Returns cleanup() => void to unmount and release listeners/timers.

Examples

Basic

Both halves:

import { enableDevTools } from '@quantajs/core';
import { mountDevTools } from '@quantajs/devtools';

enableDevTools();
mountDevTools();

Mounting the UI without enabling the bridge produces an empty panel.

Custom Target

mountDevTools({ target: '#devtools-root' });

Error Hook

mountDevTools({
  target: '#missing-root',
  onError(error) {
    console.warn(error.message);
  },
});

Dynamic Import (Production-Safe)

if (import.meta.env.DEV) {
  enableDevTools();
  import('@quantajs/devtools').then(({ mountDevTools }) => {
    mountDevTools();
  });
}

DevTools Component

Low-level Preact component for manual composition.

import { render } from 'preact';
import { DevTools } from '@quantajs/devtools';

render(<DevTools />, document.body);

For React apps, prefer QuantaDevTools from @quantajs/react/devtools.

Bridge Events (for context)

Once enabled, the bridge emits:

  • STORE_INIT
  • STATE_CHANGE
  • ACTION_CALL

The UI subscribes to these; you do not wire it up yourself. A listener that throws is contained and can no longer break application state writes, which it could in 2.0.0.

Learn More

Spot something that needs improving?

Edit page