Skip to content

feat(preview): add flows config preview command - #14

Merged
mlnchk merged 12 commits into
mainfrom
feat/byo-preview-cli
Aug 19, 2026
Merged

feat(preview): add flows config preview command#14
mlnchk merged 12 commits into
mainfrom
feat/byo-preview-cli

Conversation

@mlnchk

@mlnchk mlnchk commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Adds flows config preview <config_file>: turns a local flow config into a render URL for the dashboard's /flow-preview route. No API call, no --app, no browser automation.

What changed

  • flows config preview <config_file> — reads a local JSON config, normalizes it, and builds the render URL. Flags: --screen, --device (default iphone-14), --orientation (portrait|landscape, default portrait), --json.
  • lib/preview.ts — normalization + URL/fragment building. Accepts a dashboard-api envelope ({config, remote_configs, …}) or a bare builder config; both become {flow, remoteConfigs}. screens must be an array, mirroring the render page's own payload guard, so a config the page would reject fails here with a message instead of rendering nothing.
  • lib/app-url.ts — dashboard host from ADAPTY_APP_URL (default https://app.adapty.io). The /flow-preview path is fixed; there is no URL flag.
  • auth login — now rehosts the API-issued verification link onto ADAPTY_APP_URL, so pointing the CLI at a local or staging dashboard keeps the browser there. Only when the env var is set: the API serves that link from auth.adapty.io by default, and forcing the app host unconditionally would break production.

Design

Fragment format#config=<base64url(gzip(utf8(json)))>, gzipped unconditionally, no prefix. Matches the render page's decoder, which compresses too, so there is no plain shape to mark it apart from. The payload keys stay camelCase ({flow, remoteConfigs}) because that object is a wire contract with the UI, unlike the CLI's own snake_case output.

Output depends on where stdout goes, because the URL is far too long to read:

context output
TTY opens the browser, prints a one-line confirmation
piped / redirected the bare URL, nothing else
--json {render_url}, never opens a browser

Capture is the caller's job. The CLI owns the fragment format (it must stay in lockstep with the page's decoder) but not screenshotting, so Playwright is not a dependency and no reference script ships here — that lives with the flow skill. Callers pipe the URL into whatever takes the shot:

adapty flows config preview flow.json --screen scr_abc | node capture.mjs --out shot.png

Scope limit, documented in help and both docs

This is a quick-look escape hatch for small configs. Past roughly 32KB of pretty-printed JSON the render page becomes slow and unreliable — trim to the screen you are working on rather than throwing a whole flow at it.

Separately, the URL is long even when it renders fine (~113K characters for a 668KB flow), so it must never be printed or read; agents that let it land in their transcript burn context for zero information. --help, the README callout and skills/adapty-cli/references/cli-commands.md all say so, with the pipe form first and --url "$(…)" as the fallback for tools that want a flag.

There is deliberately no file-based hand-off flag. An earlier --payload-out emitted the payload to a file and the fragment in the URL, which repeated the whole config in output an agent has to read (227KB on a real flow). Verified since then: a 113KB fragment navigates and decodes fine in headless Chrome, and a pipe carries it with no size limit, so the flag was dropped rather than fixed.

Testing

test/lib/preview.test.ts, test/lib/app-url.test.ts and test/commands/flows-preview.test.ts cover normalization (both input shapes, the screens guard, malformed JSON), URL building (default and overridden host, fixed route, query params, screen omitted), the gzip fragment round-tripping byte-for-byte the way the page decodes it, auth login link rehosting with and without the env var, and the piped-vs---json output shapes — including a guard that the output never grows to twice the fragment, which is what caught the duplication above.

Whole suite: 164 passing, lint and check:agent-docs clean.

🤖 Generated with Claude Code

@mlnchk
mlnchk merged commit a7a37ac into main Aug 19, 2026
4 checks passed
@mlnchk
mlnchk deleted the feat/byo-preview-cli branch August 19, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant