About flow-preview
A skill and Node.js CLI for generating temporary, self-contained previews of real UI flows. It helps teams inspect interface states and interactions without creating a second production-like UI; fixture previews do not validate backend operations.
Key features
- 01Generates previews from a project root
- 02Maps UI states into a navigable canvas
- 03Uses production components with local fixtures
- 04Supports review marks and local persistence
- 05Includes layout, keyboard, and motion checks
Use cases
- 01Map success, loading, and failure states for a UI
- 02Review branches of an interaction flow
- 03Inspect a component across light, dark, and narrow layouts
- 04Share a temporary preview portal from an Amp orb
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ tanishqkancharla/ flow-preview --skill flow-previewAfter installing, type/flow-previewin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
.oxlintrc.json.gitignoreREADME.mdpackage.jsonplaywright.config.tsNOTICELICENSEpackage-lock.jsontsconfig.jsonassets/FlowCanvas.tsxpreviewConfig.mjsscripts/generate.mjstest/FlowCanvas.spec.tsfixtures.tsDetails
From the project READMEFlow preview
Generate a temporary, self-contained preview using this skill's scripts/generate.mjs. Keep this entire skill folder together when moving it. The CLI uses only Node built-ins and works from any project's root, without Halo packages or workspace configuration. The canvas is a development tool, not production application state.
Derive the story from the real UI
- Read the production component, its consumers, and its state transitions. Map the user's entry point, actions, success, loading, validation, failure, retry, and permission branches that matter to the request. Do not invent screens to fill a grid.
- Adapt the actual production component through props and local fixture callbacks. If it combines server calls with rendering, propose a small presentational extraction; do not maintain a second lookalike UI.
- Keep fixtures and simulated requests in the temporary preview, not production conditionals. Thumbnails mount every state simultaneously: rendering them must not send requests, start real work, or mutate production data. Use deterministic values, not timestamps or random content.
- Use the Maui skill, when available, for UI composition. Keep flow-specific copy and business data in the scenario/adapter, not the generic canvas.
- Render the production UI without added surface labels, headers, instruction panels, or simulation-disclaimer footers. Put context in the node's
note. Show only the local simulation buttons needed for the current state, with explicit action labels such as “Simulate grant access”; do not add a “Preview controls” header. - Keep map thumbnails unframed at rest. On hover, show one background around the whole node: title, review checkbox, and thumbnail, including the gaps between them. Preserve the production component's own surfaces. Only the selected interactive preview gets a gallery-style dotted panel, with the UI centered inside it. Use plain state titles without number prefixes; the graph and outline already communicate order.
Generate and serve
From the target project's root, run the script at its installed skill location. The Skills CLI normally installs it at .agents/skills/flow-preview; adjust the path if your agent uses a different directory:
node .agents/skills/flow-preview/scripts/generate.mjs preferences-flow 4180
npm --prefix tmp/preferences-flow install --workspaces=false
Arguments are <lowercase-name> [port]; the default port is 4180. Names cannot contain paths. Existing previews are never overwritten. The script creates tmp/<name>/ relative to the current directory, not relative to the skill. It copies the canvas and Vite helper alongside scenario.tsx, main.tsx, index.html, vite.config.mjs, and a private package.json. Generated previews do not import from this skill or from Halo; the skill can move without breaking them.
Edit tmp/<name>/scenario.tsx. Install dependencies in that preview only; do not add it to the project's workspace. When importing real application components, align React and Maui versions with that project and retain the Vite helper's deduplication. In vite.config.mjs, pass only the required source directories as sourceRoots to previewConfig (paths are relative to the preview directory, for example sourceRoots: ["../../packages/web/src"]). The default allowlist covers the preview directory only; never allow the project root or runtime workspace. Credential files, .git, .halo, and .amp remain denied even inside an allowed source directory. Verify these boundaries through HTTP before sharing a portal.
In an Amp orb, follow the exact supervised command printed by the script:
amp orb service start flow-preferences-flow --command 'npm --prefix tmp/preferences-flow run dev' --port 4180 --portal
Share the returned portal URL; do not share localhost or direct orb host URLs. Outside an orb, use npm --prefix tmp/preferences-flow run dev. Stop the service before removing its preview directory. Never start preview servers with nohup or a shell background process in an orb.
Describe states
FlowScenario and FlowNode are exported from the generated ./FlowCanvas.tsx:
- Scenario: stable
id,title,initialState, andnodes; optionaldescription,navigationLabel, anddimensions. - Each node: unique stable
id,title,action(incoming user action), optionalparent, nonnegativerow, andrender({ mode }). Keep parents before children; roots omitparent. The initial state must exist. Use a separate occurrence ID when a journey revisits a state rather than creating a cycle. - Columns follow parent depth and pack vertically without empty slots.
roworders states within their own column; it does not reserve a global lane. Arrows still connect the actual parent and child, even when their vertical positions differ. renderreturns the real component adapter.modeisthumbnailorpreview; use distinct DOM IDs for each. Keep the visible content equivalent. Optionalnoteappears only in the interactive preview, never beneath thumbnail titles.dimensions:previewWidthis the default unscaled component width;nodeWidthis the thumbnail width andnodeHeightits maximum height. Each node can setmaxWidthandmaxHeightin unscaled pixels. Use the production component's existing width cap so its content fills the thumbnail instead of shrinking inside unused space. The interactive UI fills available width up to that cap, grows with its content, and scrolls at the smaller of its height cap (by default the unscaled thumbnail height) and the available pane height. Keep the title and navigation outside that scroll area. Shorter previews shrink to their rendered height, including their hit targets and arrow anchors. Title rows use their natural height, not a fixed-height heading slot.columnGap/rowGapseparate branches. Set the maximum height large enough that relevant content is visible.
The canvas supplies the hierarchical outline, title/checkbox above each thumbnail, pan by scrolling, zoom, animated selection/crossfade, reset, and animated sidebar toggle. Keep preview chrome to the state title, review checkbox, reset, and navigation actions; do not repeat “Interactive preview” or “Follow this flow” headings. Both sidebars use Maui's raised element surface. Thumbnails have no enclosing card surface or border at rest. A single native CSS :hover on the whole node supplies an instant Maui hover background, without transitions, geometry changes, or title-color changes. The header, checkbox, thumbnail, and their gaps stay inside that continuous hover area. Keep the selection button transparent on native :hover, not only React Aria's delayed data-hovered, to prevent a first-frame fill flashing over the UI. Selection makes the title accent-colored and semibold. Clicking the title or thumbnail selects the state; the checkbox only changes its review. Hovering does not select or reset a state. Outgoing scenes and thumbnail contents are inert; use the interactive preview to exercise their controls. Reduced motion removes travel while retaining the crossfade.
Center the selected UI in a panel matching Maui gallery's Panel recipe: gray-1 surface, gray-alpha-3 dots at 12px intervals, outline border, and extra-large radius. Use the same dotted background recipe for the map canvas. Use an even, compact inset on all four sides and no minimum panel height; cap the panel itself at the UI width plus its inset and border rather than leaving wider side gutters. The padded panel owns scrolling, not a tight wrapper around the UI: preserve the production component's shadow instead of clipping it into corner marks. Give thumbnails a small overflow clip margin for shadows while still bounding tall content. Preserve padding owned by the production UI. This is gallery styling, not a Panel package import. Keep Previous state and forward actions outside that panel, right-aligned with the same default button styling. Do not add a disclaimer footer. Both sidebar boundaries support dragging and keyboard resizing; widths persist per scenario in browser localStorage. The outline selection background wraps the whole row, including its review checkbox; clicking that checkbox still only changes the review. Clamp sidebars to leave space for the map, and hide resize handles in the stacked narrow layout without replacing the saved desktop widths.
Review and verify
Review checkboxes in the outline, canvas, and interactive preview share one per-state value. A check dims only its thumbnail and overlays a green circle with a checkmark. The mark stays fully visible and does not block selecting the state. Browser localStorage stores a fingerprint per scenario/state; reset, theme changes, and reloads preserve it. Changed rendered content or style classes invalidate only the affected state. Fingerprints ignore generated IDs, theme values, and transient animation transforms/opacity. They describe the deterministic thumbnail, not an edited interactive draft. Keep scenario/state IDs stable; a new ID is a new review. Reviews are local to that browser and origin, not shared reviewer storage.
For a new scenario, drive all relevant states and real interactions in its portal. Use the using-agent-browser skill before browser work when available. Check light, dark, narrow layout, keyboard navigation, reset, review synchronization/persistence, and reduced motion. Inspect screenshots, not only DOM assertions. In an Amp orb, save reviewable final screenshots/recordings under .amp/in/artifacts/. Otherwise, use the project's artifact directory. Keep scratch captures in the preview's tmp/ folder. Do not treat a fixture preview as proof that the real backend operation succeeds.
Maintain the skill
The bundled assets/FlowCanvas.tsx and assets/previewConfig.mjs are the sources copied by the CLI. After editing those files or the generator, run from this skill's directory:
npm install --workspaces=false
npm run typecheck
npm run lint
npm run format:check
npm run test:e2e
The browser tests copy the skill to a separate consumer project, generate a notification-preferences flow, remove that skill copy, and exercise the resulting preview. Install Playwright Chromium with npx playwright install chromium if needed, or set PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH to an installed browser. This skill has no dependency on repository lint or TypeScript configuration. Changes to the skill do not silently update existing generated previews; create a new preview or deliberately refresh its copied canvas/helper while preserving scenario IDs and fixtures.