Table of Contents

Content and resource loading

For Avalonia and Uno applications, package content for the framework's WebSceneComponentHost. Both hosts validate the manifest, perform compatibility preflight, and serve only declared assets from an isolated per-instance virtual origin. Direct document URLs remain available for advanced presenter-level use.

components/
  StatusPanel/
    webscene-component.json
    dist/
      main.js
      styles.css
{
  "schemaVersion": "1.0",
  "id": "com.example.status-panel",
  "displayName": "Status panel",
  "version": "1.0.0",
  "profileVersion": "1.0",
  "entryPoint": "dist/main.js",
  "assets": [
    "dist/main.js",
    "dist/styles.css"
  ],
  "capabilities": [
    "dom",
    "css.layout"
  ]
}
<ItemGroup>
  <Content Include="components/**"
           CopyToOutputDirectory="PreserveNewest"
           CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>
<ws:WebSceneComponentHost
    PackagePath="components/StatusPanel" />

PackagePath is resolved against AppContext.BaseDirectory. The host creates a unique https://<instance>.component.webscene.invalid/ origin for each mounted instance. A request succeeds only when it stays on that origin and its normalized relative path appears in the manifest's assets array.

Component Profile 1 currently serves UTF-8 text assets. Declare the entry point and every script or stylesheet it loads. Binary assets, undeclared files, absolute external origins, .. traversal, and malformed paths are rejected by the package loader.

The entry point itself is evaluated after the empty component document and capability-gated host bridge are ready. It must publish the manifest's mount and unmount lifecycle exports on globalThis; it is not an HTML document.

See Package and host a component for a complete package.

Advanced direct-document layout

Keep the web bundle together and copy it without flattening its directory structure:

MyApp/
  web/
    index.html
    app.js
    styles.css
    assets/
      logo.svg
      app.woff2
<ItemGroup>
  <Content Include="web/**" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

When using NativeWebSceneView directly, load index.html through an absolute file URI:

var documentPath = Path.Combine(
    AppContext.BaseDirectory,
    "web",
    "index.html");
var documentUri = new Uri(documentPath).AbsoluteUri;

await webSceneView.LoadAsync(
    documentUri,
    nativeLibraryPath,
    compilationCacheDirectory,
    cancellationToken);

Relative references such as ./app.js and ./assets/logo.svg then resolve against the document directory. Avoid building file: URLs by string concatenation; Uri handles platform separators and escaping.

Direct-document resource schemes by host

The direct presenters do not expose identical resource loaders. These schemes do not change the component host's manifest-isolated resource policy:

Scheme Avalonia Uno Skia Notes
file: Yes Yes Best-supported packaged-content path
http: / https: Yes Yes Uses an internal HttpClient; HTTP cache validators are honored
data: Yes Yes Text and inline data; use only for bounded content
avares: Yes No Loads Avalonia application resources through AssetLoader

Use file: when the same bundle must run unchanged in Avalonia and Uno. Avalonia-only applications can load an avares: resource, but external files are easier to inspect, update during development, and share with native/headless fixtures.

Direct HTTP and HTTPS content

Both loaders follow relative URLs from an absolute HTTP(S) document and retain common cache metadata such as ETag, Last-Modified, Cache-Control, and Expires. An HTTP error fails the resource request rather than silently substituting empty content.

Remote loading does not turn WebScene into a safe general-purpose browser. Only load origins and content controlled by the application. The built-in views do not expose a public per-request allow/deny callback, certificate policy, cookie profile, or browser permission model.

For reproducible UI and offline behavior, prefer a versioned local bundle. If remote content is necessary, pin the endpoint, define an application-level update policy, and test failure and stale-cache behavior.

Direct Avalonia resources

The Avalonia loader understands avares: URLs:

await webSceneView.LoadAsync(
    "avares://MyApp/Assets/Web/index.html",
    nativeLibraryPath,
    compilationCacheDirectory,
    cancellationToken);

Mark the files as AvaloniaResource in the application project. Every relative resource must be reachable through the same asset URI structure. This path is specific to Avalonia and should not be used in a framework-neutral document configuration.

AvaloniaResourceLoader also exposes search-directory and mounted-directory helpers for advanced backend integrations. NativeWebSceneView creates and owns its default loader internally, so its standard public loading surface does not currently offer a hook to configure those helpers.

Document-start scripts

Set WebSceneComponentHost.DocumentStartScripts before mounting a component. When hosting a document directly, use NativeWebSceneLoadOptions.DocumentStartScripts for the same ordered startup hook:

var options = new NativeWebSceneLoadOptions
{
    Source = documentUri,
    NativeLibraryPath = nativeLibraryPath,
    CompilationCacheDirectory = compilationCacheDirectory,
    DocumentStartScripts =
    [
        new WebSceneDocumentScript(
            "globalThis.appHost = Object.freeze({ version: '1.0' });",
            "app-host.js",
            AllFrames: false)
    ]
};

await webSceneView.LoadAsync(options, cancellationToken);

Scripts execute in list order. A script exception fails the initial load and records its configured name in native diagnostics. AllFrames: true also injects the script before authored code in subsequently created frames.

Keep these scripts static and application-owned. Do not interpolate unescaped user or network data into JavaScript source. Use generated typed interop for runtime values and commands.

Storage behavior

The current native runtime supplies synchronous in-memory localStorage and sessionStorage for the engine/page lifetime. It implements the common item methods and stable insertion order, but does not promise persistence, quotas, storage events, origin/reload semantics, shared profiles, or IndexedDB.

Do not store durable application state in the WebScene storage subset. Persist through an explicit application service and expose only the narrow operations the trusted document needs.

Content update checklist

When replacing a packaged web bundle:

  1. Review the changed HTML, JavaScript, CSS, fonts, and binary assets as application code.
  2. Run the required WebScene compatibility profile plus a product-specific fixture.
  3. Regenerate and review typed interop manifests if TypeScript declarations changed.
  4. Verify the bundle from publish output, not only from the source directory.
  5. Exercise missing-resource, offline, and slow-resource behavior.

See Compatibility and security for the support and trust boundaries that apply to every content strategy.