Rask
Rask
v0.23.1-alpha.0.496
You're reading the Rask v0.23.1-alpha.0.496 guides. Updated .View source
All guides

Browser APIs

Rask reaches the browser's Web APIs two ways. Most are MDN's own surface, generated into C# by Rask.Web: await Navigator.Clipboard.WriteText("hi"), await LocalStorage.GetItem("theme"). The rest are typed C# wrappers — inject one through a component constructor and call it, instead of hand-writing IJSRuntime identifiers and getting the JSON shape right yourself. Each is a thin, awaitable layer over the same unified IJSRuntime, so it works the same way whether your app runs on the Server (WebSocket) or WASM (JSImport/JSExport) transport.

This page is the map of the whole surface. For an at-a-glance view of where each API works (Web / PWA), see the capability matrix — it links to a dedicated reference page per API under docs/apis/. For the deeper "why" — user activation, the transport seam, element refs — see JS interop → Typed browser APIs; for the mobile/PWA angle see the Mobile & PWA guide. Every wrapper has a runnable demo in the showcase, under Browser APIs — except the WASM-only tier, which gets its own page under PWA because it needs something the Server transport can't give it. (The activation-gated ones appear in both: as gesture components under Browser APIs, and as injectable services or Rask.Web calls under PWA.)

Two homes, one rule

  • Rask.Core.Browser — APIs that work on every host (Server + WASM). Registered by both.
  • Rask.Wasm.Browser — APIs only the WASM host can run: they need the installed-PWA instance, a live document, a device chooser, or transient user activation — preserved only when the interop call runs inside the click's own call stack, which the Server's WebSocket round-trip loses.

The rule: shared-everywhere APIs live in Rask.Core.Browser, WASM-only ones in Rask.Wasm.Browser. A host simply doesn't register a service it can't provide.

Sharing shows the split cleanly. The declarative, headless Shareable (Rask.Core) hands your markup a data-rask-share attribute and the shared client fires navigator.share inside the click gesture — no round-trip, so activation survives — so it works on every host, Server included. The imperative await Navigator.Share(…) from Rask.Web shares from code (a lifecycle hook, after an await), which only the WASM host can do, so it compiles only in a WASM app.

Call from an event handler or lifecycle hook, never from Render(). A typed wrapper is injected through the constructor (not a settable property — that would become a required chain parameter):

public sealed partial class ThemeToggle : Component
{
    protected override async Task OnFirstRender()
    {
        var saved = await LocalStorage.GetItem("theme");     // or: await Document.Cookie
        var dark = saved is null
            ? await Window.MatchMedia("(prefers-color-scheme: dark)").Matches
            : saved == "dark";
        // …apply theme…
    }
}

Browser-gated APIs (clipboard, geolocation, notifications, fullscreen, crypto's secure context, …) can fail — a denial/timeout/unsupported surfaces as a JSException from the awaited task, so gate on the API's IsSupported/permission check and wrap calls in try/catch.

See the capability matrix for which APIs work on which host.

On this page

Notes

  • Secure context. Clipboard, geolocation, notifications, push, crypto.subtle, and others require HTTPS or localhost.
  • Permission/support gating. Many APIs expose IsSupported(); ask Navigator.Permissions.Query(…) from Rask.Web before triggering a prompt, and try/catch the call.
  • Trimming (WASM). Types these APIs deserialize are registered in source-gen JSON contexts, and the push APIs' [JSInvokable] methods are [DynamicDependency]-rooted, so everything stays correct in a PublishTrimmed app.

See also: JS interop · Mobile & PWA.

Confirm