pyreon

@pyreon/atlas — API Reference

Generated from atlas's src/manifest.ts — the same source that powers llms.txt and MCP get_api. Do not edit this page by hand; edit the manifest. For the conceptual guide, see atlas.

Atlas inverts Storybook’s authoring-first model: your components and their TypeScript types are the source of truth, and Atlas DERIVES the catalog — controls inferred from props, scenarios generated from variant axes (rocketstyle dimensions included), and a five-check verify verdict per scenario (a11y, interaction, leak, reactivity coverage, snapshot). atlas scan writes atlas-catalog.json + atlas-agent-guide.md (the machine-readable surface an AI assistant consumes), atlas dev serves a zero-config workbench over the real Vite compiler, and atlas verify-browser runs the browser half of verification in real Chromium. Authoring is opt-in, not required: an atlas.config.ts can add a theme, a wrapper, presets (viewports / locales / roles), and authored scenarios with play interaction scripts.

Features

  • Derived catalog: controls inferred from prop types, scenarios generated from variant axes (rocketstyle dimensions resolved through the project theme)

  • Five-check verify verdict per scenario — a11y, interaction (play scripts or auto click-walk), REAL leak check (reactive-graph accumulation past GC), reactivity coverage, visual snapshot

  • Machine-readable output: atlas-catalog.json + atlas-agent-guide.md, written for AI assistants as first-class consumers

  • Zero-config workbench (atlas dev): real Vite + the real Pyreon compiler, live control editors, canvas addons (viewport/background/zoom/measure/pseudo-states), axe-core a11y panel, autodocs, Actions log, Reactivity Lens

  • Browser verification (atlas verify-browser): reactive coverage measured on the page’s own devtools bridge + pixelmatch snapshot baselines, merged into the catalog

  • Authoring opt-in via atlas.config.ts: theme, wrapper, presets (viewports/locales/roles), authored scenarios with step-labelled play functions

  • Honest verdicts by construction: three states (verified/failing/unverified), red scan = red exit, partial browser coverage named per scenario

Complete example

A full, end-to-end usage of the package:

// atlas.config.ts — ALL of this is optional; scan/dev work with none of it.
// Named exports, plain values, no JSX (the scan imports this file under
// whatever runtime it runs — see the workshop's atlas.config.ts).
export const presets = {
  viewports: [
    { id: 'full', label: 'Full', width: null },
    { id: 'kiosk', label: 'Kiosk', width: 900 },
  ],
  locales: [
    { id: 'en', label: 'English' },
    { id: 'ar', label: 'Arabic', dir: 'rtl' as const },
  ],
  roles: [
    { id: 'anonymous', label: 'Anonymous', hint: 'nothing granted' },
    { id: 'ops', label: 'Ops', grants: ['posts.delete'] },
  ],
}

export const scenarios = {
  Button: [
    {
      name: 'Triple click',
      args: { label: 'Storm target' },
      play: async ({ root, step }: { root: Element; step: (n: string, r: () => void | Promise<void>) => Promise<void> }) => {
        await step('find the button', () => {
          if (!root.querySelector('button')) throw new Error('no button')
        })
        await step('click it three times', () => {
          const target = root.querySelector<HTMLButtonElement>('button')!
          for (let i = 0; i < 3; i += 1) target.click()
        })
      },
    },
  ],
}

// A project can also export `theme` (resolves rocketstyle dimension axes)
// and `wrapper` (the providers your components genuinely need to mount).

// Then:
//   bunx atlas scan .            → atlas-catalog.json + atlas-agent-guide.md
//   bunx atlas dev .             → the workbench at localhost:5210
//   bunx atlas verify-browser .  → coverage + snapshot verdicts in Chromium

Exports

SymbolKindSummary
atlas scanfunctionDiscover components (static TS scan + rocketstyle runtime detection), derive controls and variant scenarios, MOUNT each
atlas devfunctionBoot the workbench: real Vite + the real Pyreon compiler over your source, a derived catalog in the sidebar (nested by d
atlas verify-browserfunctionThe browser half of verification, in real Chromium (playwright-core is an OPTIONAL peer — scan/dev work without it).
createAtlasfunctionThe programmatic pipeline factory behind the CLI: discover → decorate → verify → graph, plugin-driven.
AtlasConfig.scenarios (authored scenarios + play)functionAuthored scenarios in atlas.config.ts, keyed by component name.

API

atlas scan function

atlas scan [dir] [--no-mount]

Discover components (static TS scan + rocketstyle runtime detection), derive controls and variant scenarios, MOUNT each scenario (real module load through a Vite-powered loader) and run the node half of the verify pipeline — a11y (static), interaction (mount + play/click-walk), and a REAL leak check (reactive-graph accumulation across repeated mounts, past GC). Writes atlas-catalog.json (every component, control, scenario, and verdict) and atlas-agent-guide.md (the AI-consumable summary). Exits non-zero when any scenario FAILS — wiring the scan into CI gates the catalog. --no-mount keeps the scan purely static (no project code executes).

Example

$ atlas scan .
atlas: discovered 9 component(s), 43 scenario(s)41 verified, 2 failing, 0 unverified.
atlas-catalog.json
atlas-agent-guide.md
atlas: 2 failing scenario(s): button--empty, badge--empty

Common mistakes

  • Treating "verified" as a default — a scenario is verified only when a check actually RAN and passed; checked: 0 renders as unverified, never smoothed into a pass

  • Running the scan without the project theme in atlas.config.ts for rocketstyle components — dimension axes resolve empty and the variant scenarios collapse to defaults

  • Expecting the leak check under plain node — it needs a GC hook (bun, or node --expose-gc); without one it reports skip, not pass

  • Expecting reactivityCoverage/snapshot verdicts from the scan — those are browser-only claims; run atlas verify-browser to earn them

See also: atlas verify-browser · createAtlas


atlas dev function

atlas dev [dir] [--port=5210]

Boot the workbench: real Vite + the real Pyreon compiler over your source, a derived catalog in the sidebar (nested by directory), live controls (bool/string/number/color editors), canvas addons (viewport / background / zoom / measure overlay / pseudo-state force), an A11y panel with on-demand axe-core, autodocs pages, an Actions log, and the Reactivity Lens. Components in files that import @pyreon/atlas are treated as workbench HOSTS and excluded from the nav (import-specifier match, never substrings).

Example

$ atlas dev . --port=5210
atlas dev: 9 component(s) → http://localhost:5210/

Common mistakes

  • Expecting authored play functions to run on DERIVED catalogs in the workbench — play crosses no JSON boundary; the ▶ button appears for hand catalogs, and derived play scripts run in atlas scan / the verify pipeline

  • Styling per-instance frames with inline styles — the workbench styles through the Element css prop channel (hashed classes); custom viewport widths ship zero inline styles

See also: atlas scan


atlas verify-browser function

atlas verify-browser [dir] [--update-snapshots]

The browser half of verification, in real Chromium (playwright-core is an OPTIONAL peer — scan/dev work without it). Boots the workbench, drives every derived scenario through the workbench model, measures reactive coverage on the page’s own devtools bridge (the components’ actual reactivity instance — a NEW-NODE diff so workbench chrome never pollutes the numbers), screenshots the preview against per-scenario pixelmatch baselines under atlas-snapshots/, and merges both verdicts back into atlas-catalog.json. Coverage is a MEASUREMENT, not a threshold gate: pass means measured, and the findings carry the numbers. First run creates baselines (flagged as recorded-not-yet-compared); later runs compare within tolerance and write <id>.actual.png on a diff. Exits non-zero on visual diffs.

Example

$ atlas verify-browser .
atlas verify-browser: 26 scenario(s)coverage measured on 26, 0 baseline(s) created, 0 visual diff(s).
atlas-catalog.json

Common mistakes

  • Committing atlas-snapshots/ across machines — baselines are machine-specific (font antialiasing); gitignore them and let each environment create its own on first run

  • Reading "100% of 0 reactive nodes" as broken — a genuinely static scenario creates no reactive nodes and the finding says so explicitly

  • Treating not-drivable scenarios as failures — components living in workbench-host files can’t be driven through the dev nav; the summary names them and their browser verdicts stay skip

See also: atlas scan


createAtlas function

(options?: { plugins?: AtlasPlugin[]; preset?: "recommended" | "none" }) => Atlas

The programmatic pipeline factory behind the CLI: discover → decorate → verify → graph, plugin-driven. The recommended preset bundles the built-in plugins (controls inference, variant matrix, mount/interaction/leak verification). Pass preset: "none" when you assemble the plugin list yourself — appending the recommended bundle on top of an explicit list runs duplicate plugins whose default verdicts can overwrite real ones.

Example

import { createAtlas } from '@pyreon/atlas'

const atlas = createAtlas()            // recommended preset
const graph = await atlas.build()      // discover → decorate → verify → graph
graph.search('button')                 // Catalog Graph queries

Common mistakes

  • Passing an explicit plugin list WITHOUT preset: "none" — the recommended bundle is appended a second time and a duplicate mount plugin’s empty-graph default verdict can overwrite the real one

See also: atlas scan


AtlasConfig.scenarios (authored scenarios + play) function

Record<string, { name: string; args?: Record<string, unknown>; play?: PlayFn }[]>

Authored scenarios in atlas.config.ts, keyed by component name. Authored entries are prepended and WIN over generated scenarios with the same id. A play function receives { root, step }root is the mounted scenario’s container, step(name, run) labels each phase; a throw fails the interaction check naming the exact step. Validated at load: unknown fields error with the correct field name.

Example

scenarios: {
  Button: [{
    name: 'Submit flow',
    args: { label: 'Save' },
    play: async ({ root, step }) => {
      await step('click', () => root.querySelector('button')!.click())
    },
  }],
}

Common mistakes

  • Expecting play to serialize into atlas-catalog.json — functions never cross the JSON boundary; the catalog records the verdict the play run produced, not the script

See also: atlas scan · atlas dev


Component Workbench — API Reference