@flow-as-code/studio design

A local-first visual editor over FlowDoc, with live bidirectional sync to typed builder code, and CDK or Terraform files as the export targets. This goes one step past both the Connect console (visual, but ARN-bound and instance-bound) and FlowLang (typed code and console round-trip, but proprietary and not IaC-native): visual editing whose output is IaC.

Delivery

Canvas

Bidirectional sync (the core trick)

The bridge (flow-cli studio)

The browser cannot write files, so the CLI does. One node:http server serves the built studio and a small JSON API; the studio talks to it through the DocStore seam and nothing else in the app touches persistence.

Export targets (in-app buttons and CLI parity)

All three run over the whole document set, which is what the IaC targets mean: one terraform configuration, one binder covering every reference type in the set. Parity with the CLI is enforced by construction and then tested. The generators are shared modules rather than reimplementations (@flow-as-code/cdk/scaffold behind both the CLI's emit --target cdk and the studio's button, @flow-as-code/tf/emit, @flow-as-code/core's materializeWithMap), and a test in @flow-as-code/studio runs the built CLI as a subprocess and compares the bytes.

Terraform needs an address per reference, so that target carries a map editor: every reference in the set with its type and name, an address field each suggesting the resource type that reference actually needs, and a count of what is still unmapped. A literal ARN is refused inline, the same rule the ref pickers apply to parameters. What counts as unmapped is read back from the emitter's own TODO output rather than recomputed, so a reference the set resolves itself needs no entry. The raw target's resource map is the opposite case and takes ARNs, since its output is deployable Flow language; an incomplete map refuses the export and lists every missing token.

Exporting is a write path, so it runs the same save gate as a save: a document failing a hard lint rule or the schema cannot be exported by any target, and the check lives in the export functions rather than in the buttons.

Delivery has two ends and one code path. Under flow-cli studio the emitted file map is POSTed to the bridge, which writes it (the CLI is the only thing that touches disk, and it re-checks every path); with no bridge the browser downloads the files, folding each directory into the file name because a browser cannot create one. The bundle is built once, before either end sees it.

Explicitly out of scope for v1

Multi-user editing, cloud storage, Connect console import-file parsing (not Flow language), TF-to-FlowDoc reverse parsing, telemetry.