Skip to content

feat(dart): build the web target's assets instead of scripting them - #60

Merged
nikzen merged 4 commits into
feat/supply-chainfrom
feat/flutter-web-assets
Aug 3, 2026
Merged

feat(dart): build the web target's assets instead of scripting them#60
nikzen merged 4 commits into
feat/supply-chainfrom
feat/flutter-web-assets

Conversation

@nikzen

@nikzen nikzen commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

A Flutter web application needs two compiled artefacts in web/ that no
repository should carry: the vodozemac WebAssembly module with its glue, and
LiveKit's frame-encryption worker. famedly/call produces them with a
prepare-web.sh that clones two repositories, cargo installs a code
generator and pins the worker to a branch name by hand. This replaces that.

  • The bindings become a package. The native library and the WebAssembly
    module are the same crate compiled twice, so both now come from one pinned
    source and the Dart package can never talk to bindings from another revision.
    Everything vodozemac moves under nix/dart/vodozemac/ on the way.
  • The worker is compiled from the package the project already resolved. Its
    location comes out of .dart_tool/package_config.json, so it follows
    pubspec.lock and needs no pin of its own.
  • One script does both, and the devshell carries it. An asset only CI knows
    how to produce is one a developer cannot reproduce when the site misbehaves in
    the browser.

wasm-pack runs directly rather than through flutter_rust_bridge_codegen build-web, which is a Dart program that only shells out to it — that keeps a
Dart toolchain and a pub cache out of the build. The price is that the flags
live here, and flutter_rust_bridge has changed them between versions, so the
build fails with an explanation if the crate stops pinning the version those
flags were read off.

Stacked on #56, whose build.nix this extends.

Test plan

  • nix flake check --all-systems
  • nix build .#famedly-vodozemac-web: the module carries the threading
    instructions the browser needs, and the two files match byte for byte what
    prepare-web.sh produces today
  • ran the generated script in famedly/call: both assets land where they are looked for, the
    worktree stays clean, under two seconds
  • the generated workflow runs it before flutter build web
  • a full web build in CI

Made with Cursor

nikzen and others added 3 commits August 3, 2026 16:04
A Flutter web application needs the WebAssembly module and its glue, which
the native library is not a variant of. Both are cut from one pinned source
now, so the Dart package can never talk to bindings from another revision.

Collects everything vodozemac under nix/dart/vodozemac/ on the way.

Signed-off-by: Niklas Zender <n.zender@famedly.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
A Flutter project depends on flutter_vodozemac, not on the plain package, and
the hook then found no constraint at all and failed every commit. Both names
are cut from the tag the bindings are built from.

Signed-off-by: Niklas Zender <n.zender@famedly.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The vodozemac module and LiveKit's encryption worker are compiled artefacts of
dependencies that a web build expects in web/, and a repository that carried
them would carry copies that silently age.

The worker is compiled from the package the project already resolved, so it
follows pubspec.lock instead of a second clone pinned by hand. One script does
both, and the devshell carries it: an asset only CI can produce is one a
developer cannot reproduce when the site misbehaves in the browser.

Signed-off-by: Niklas Zender <n.zender@famedly.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread nix/dart/web/assets.nix
`./pkg/` is the default `wasmPath` of both the plugin and the plain package, so
an application that gets the module from us now needs to pass nothing at all.
An application that passes a path of its own has to drop it.

Signed-off-by: Niklas Zender <n.zender@famedly.com>
@nikzen
nikzen merged commit 03666da into feat/supply-chain Aug 3, 2026
3 checks passed

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 897a0c9. Configure here.

Comment thread nix/dart/web/assets.nix
++ lib.optional projectConfig.web.livekitE2eeWorker.enable ''
# The worker's own imports resolve through the project's package
# config, which is also where the package it lives in is recorded.
[ -f .dart_tool/package_config.json ] || flutter pub get

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pub get pulls example deps

Medium Severity

Issue: When package_config.json is missing, the LiveKit asset step runs flutter pub get without --no-example, so CI also resolves a project's example/ pubspec. That can fail or drift the lockfile on apps that ship an example, and it contradicts the checks workflow which already avoids this.

Fix: Use flutter pub get --no-example.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 897a0c9. Configure here.

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.

2 participants