Build a package widget
A package micro widget is a small web interface that runs inside a sandboxed iframe. Write it in TypeScript or a UI framework, declare its inputs, events, and queries, then distribute its built files in a Flow-Like package. A Flow supplies data and handles the events that the widget emits.
Use an A2UI Widget when a reusable declarative component graph fits the task. Use a package widget when you need custom rendering or a framework library. Both can appear in an app interface, but they have separate authoring and distribution paths.
Prepare a counter package
Section titled “Prepare a counter package”Install Bun and clone the Flow-Like repository as described in Building from Source. The following commands run from that checkout and create a sibling project:
mkdir -p ../hello-widgets/widgetscp -R templates/widget-vanilla ../hello-widgets/widgets/vanillacd ../hello-widgetsCreate flow-like.toml at this project’s root:
manifest_version = 2id = "com.example.hello-widgets"name = "Hello Widgets"version = "0.1.0"description = "A counter with typed inputs and events"keywords = []widget_bundle_path = "widgets.flwb"
[permissions]memory = "standard"timeout = "standard"The directory structure matters. The bundler discovers framework groups under
widgets/<group>/, and widgets under each group’s src/widgets/<id>/.
The copied template includes a counter and a weather example; start with the
counter, which needs no network access.
hello-widgets/ flow-like.toml widgets/vanilla/ package.json vite.config.ts src/widgets/hello-widget/ widget.config.ts index.html index.tsPreview and inspect the contract
Section titled “Preview and inspect the contract”Install the group’s dependencies and start its Vite server:
bun install --cwd widgets/vanillabun run --cwd widgets/vanilla devOpen http://localhost:5173/src/widgets/hello-widget/index.html (or the port
Vite prints). You should see Hello from Vanilla TS and a Count: 0
button. Clicking it increments the count. Without a Flow-Like host, the SDK
uses contract defaults and logs the increased event to the browser console.
Run window.__flw.query("getCount") in that console to read the counter.
For a host preview, stop Vite and run from the package root:
bunx @flow-like/widget-bundler dev --project . --port 4700Open http://localhost:4700/. Select hello-widget, change its title and
count inputs, click the counter, and inspect the increased event. Invoke
getCount to check the result. The harness also provides theme and viewport
controls. See the contract guide before
changing these inputs or events.
Build and validate
Section titled “Build and validate”Stop the development server, then run from the package root:
bun run --cwd widgets/vanilla buildbunx @flow-like/widget-bundler validate .bunx @flow-like/widget-bundler pack --project . --out widgets.flwbbunx @flow-like/widget-bundler validate widgets.flwbThe build writes the framework output into widgets/vanilla/dist/. Packing
combines it with the extracted contracts into widgets.flwb. Rebuild the
group before packing whenever its source changes. The manifest’s package ID
and version are copied into the bundle.
Preview in Desktop and install
Section titled “Preview in Desktop and install”- Enable Developer Mode, then open Packages → Mine.
- Select Add folder and choose the
hello-widgetsroot containingflow-like.toml. - Open the package’s Debug & test view and use Preview widgets to inspect the built counter through the desktop widget host.
- Choose a package ID you control before publishing. Build and pack again if you change the ID or version.
- Select Publish…, review the extracted widgets, and follow the registry workflow. Publish only when you intend to distribute that version.
- Install the available package version from Packages on the target device and add it to the app’s packages. See installed packages for device and app scope.
Use Instantiate Widget to select the package widget in a Flow. Its contract supplies the input pins. Update Widget Inputs sends new values; Query Widget invokes declared queries. Bind the widget’s emitted actions to the app’s handler before relying on them to change application data.
In an online App the package version the App pins decides those input pins, for every member and for cloud runs. A folder on your computer that declares other inputs under the same version number shows them only on that computer: when the Flow syncs, an input the pinned version does not declare is removed again unless it is connected. Publish the new version and update the App’s pin, or try the change in an offline App first.
Add framework or network features
Section titled “Add framework or network features”The repository also has React, Preact, Vue, Svelte, Solid, and Lit templates. Each framework group builds separately before the package is packed. Keep widget IDs unique across groups and use host theme variables for colors.
Network destinations require purpose declarations and viewer approval. Follow Network access and consent and test the declined-permission state as well as the successful request.