vercel-labs / vercel-labs/native
allow scene (canvas-first) apps to configure the zero://app asset root
Nobody has claimed this yet.
- Dominant language
- Zig
- Stars
- 7.7k
- Forks
- 314
- Avg merge
- 5h
- Merged PRs (30d)
- 13
Description
Environment
- native-sdk v0.4.2
- macOS aarch64
- Zig 0.16.0
What happens
NativeSdkAssetSchemeHandler and configureWithRootPath: exist in the
macOS host and back the zero://app asset scheme, but the asset root is
only ever configured as a side effect of a main-webview loading an
assets-source URL. A UiApp scene (canvas-first) app never performs that
main-webview assets-source load — the whole point of a scene app is that
the primary surface is the native canvas, not a webview. As a result, any
scene-declared webview pane (UiApp.Options.web_panes, a .webview shell
view anchored into the canvas layout) has no working asset root and cannot
load zero://app/... content.
What I expected
I expected a scene app to be able to opt into the zero://app asset root
independently of whether it ever loads a main webview — e.g. because it
hosts one or more secondary webview panes that need to load bundled static
assets (HTML/CSS/JS/images) from the app bundle.
What we did instead (workaround)
Without a configured asset root, the only way we found to serve static
content into a scene-declared webview pane is to spawn a loopback HTTP
server via the effects channel (fx.spawn sh -c "python3 -m http.server ... --bind 127.0.0.1 ...") and point the pane at
http://127.0.0.1:<port>/..., adding that origin to
security.navigation.allowed_origins. This works (verified end-to-end,
including clean teardown of the spawned process on app exit), but it's
extra moving parts — a subprocess, a startup race between the pane's first
navigation and the server binding (we handle it with a reload_token
bump-until-loaded pattern), and a port to manage — for what should be
static, bundle-local content.
Repro / code pointers
(Line numbers from the v0.4.2 npm-distributed sources.)
- Host-side plumbing that already exists:
NativeSdkAssetSchemeHandler(src/platform/macos/appkit_host.m:628),
configureWithRootPath:entryPath:spaFallback:(appkit_host.m:6201). - The only caller of
configureWithRootPath:is the main-webview
loadSource:path (appkit_host.m:9207, source kind = assets), which
UiAppscene apps never exercise. Per-window handlers are created only
insideensureMainWebViewForWindowId:(appkit_host.m:6633, stored at
:6668); scene/child webview creation reuses them via
assetHandlerForWindowId:(appkit_host.m:6691, consumed at:7314) —
so in a canvas-first app the lookup returns nil and the pane's
WKWebViewConfigurationgets nozeroscheme handler at all. - Repro app:
spike/canvas-web/— aUiAppshell hosting aWKWebView
pane viaUiApp.Options.web_panes, a scene-declared.webviewshell
view parented to the canvas and anchored to a panel's layout frame. The
pane currently loads content from the loopback server described above
rather thanzero://app.
Suggested direction
We're building an image-optimization app where the comparison canvas is a
WKWebView pane (a pure-native tiled canvas tops out around 26–32 fps at
full-canvas coverage in our measurements, well short of a webview pane's
~119 fps sustained; see our companion perf report). Static assets
(comparison-page HTML/CSS/JS) are exactly the kind of bundle-local content
zero://app seems designed for. A manifest field (e.g. under .shell or
per-webview-pane config) or a RunOptions/Runtime API call to set the
asset root explicitly — without requiring a main-webview assets-source
load to happen first — would let scene apps drop the loopback server
entirely for static content. If there's a reason the asset root is tied to
the main-webview load specifically (security scoping, bundle path
resolution timing, etc.), we'd be glad to hear the constraint — happy to
help test an API shape against spike/canvas-web/.
Related: #101, #103 — the companion issues referenced above
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the existing handler and configuration flow in src/platform/macos/appkit_host.m, especially NativeSdkAssetSchemeHandler, configureWithRootPath:entryPath:spaFallback:, ensureMainWebViewForWindowId:, assetHandlerForWindowId:, and the loadSource: caller. Reproduce the current behavior with spike/canvas-web and trace how the scene pane obtains its WKWebViewConfiguration. Done means a canvas-first scene can explicitly configure zero://app for bundled assets without a main-webview assets-source load, while preserving the existing main-webview path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, zig
- Domain
- desktop, web-dev
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100