Runtime API
These modules run in the browser. The generated client already starts the router or mounts islands, so most apps only use a few of these functions from islands. Everything is typed; this page lists what each export is for.
| Entry point | Use it for |
|---|---|
fuzor/runtime | The SPA router, navigation adapters, URL atoms, and re-exports of the two modules below |
fuzor/runtime/islands | Mounting islands yourself, island error handling, route params |
fuzor/runtime/data | Server data in islands |
fuzor/runtime/docs-ui | Shipped docs UI lifetime, deferred components, theme state and search (started automatically by docs mode) |
fuzor/runtime/docs-search | Standalone Effect-owned docs search runtime |
fuzor/ui/resume | Deferred component activation and Effect Atom checkpoints |
fuzor/runtime/navigation, …/navigation/browser, …/history, …/hash, …/memory, …/coordinator | Individual navigation pieces, for the smallest bundles |
Router
getRouter(document?)
Returns the router started by the generated SPA client, or undefined in MPA builds and before it starts.
import { getRouter } from "fuzor/runtime";
const router = getRouter();
const outcome = await router?.navigate("/checkout/");
if (outcome?.status === "failed") console.error(outcome.error);
createRouter(outlet, options)
Creates a router for an outlet element. Only needed when you write your own client entry. Options:
| Option | Meaning |
|---|---|
islands | Registry: island name → () => import(...) |
base | Deployment base path, normally import.meta.env.BASE_URL |
onError | Receives route, island and data errors |
islandTimeouts | { mountTimeoutMs, cleanupTimeoutMs } |
navigation | An injected adapter, for tests or non-browser hosts |
viewTransitions | Animate page changes with the View Transitions API where supported |
prefetch | "intent": load a page's island modules on link hover or focus |
acceptsUrl | URL policy for custom protocols in embedded hosts |
Router methods
| Method | Returns | Meaning |
|---|---|---|
start() | Promise<() => Promise<void>> | Starts routing; idempotent. The result stops it. |
dispose() | Promise<void> | Stops routing and cleans up islands |
navigate(href, options?) | NavigationResult | Navigates. Resolves to a NavigationOutcome when finished; .committed resolves when the URL changed. Options: history, state, scroll, focus, document. See navigating from code. |
block(blocker) | () => void | Registers a navigation blocker; call the result to remove it |
path(), subscribe(listener) | route path | Current route path without base, such as /docs/ |
url(), subscribeUrl(listener) | full URL | Including query and hash |
params(), subscribeParams(listener) | Record<string, string> | Dynamic route parameters |
route(), subscribeRoute(listener) | RouteMatch | { kind: "page" | "not-found", path, pattern?, params } of the current page |
state(), subscribeState(listener) | NavigationState | Phase of the latest navigation: requested, resolving, ready, committing, activating, completed, cancelled or failed, with route once resolved and error when failed |
navigation() | NavigationAdapter | The active adapter, for URL atoms |
Subscriptions return a function that unsubscribes.
Typed links
href(pattern, params?, options?)
Builds an app URL from a route or endpoint pattern and encodes its parameters. With the generated .fuzor/routes.d.ts, unknown patterns and missing or extra parameters are type errors. options: base, search (object or URLSearchParams), hash. See typed links.
FuzorRoutes is the interface the generated file augments, and RoutePattern the union of its keys (or string without it).
URL state
makeNavigationUrlAtom(navigation, key, schema, initialValue, options?)
An Effect that creates a schema-checked value stored in one query parameter. It lives in the surrounding Effect scope.
import * as Effect from "effect/Effect";
import * as Schema from "effect/Schema";
import { getRouter, makeNavigationUrlAtom } from "fuzor/runtime";
const program = Effect.scoped(Effect.gen(function* () {
const page = yield* makeNavigationUrlAtom(getRouter()!.navigation()!, "page", Schema.Number, 1);
page.subscribe(value => console.log("page", value));
yield* page.set(2); // replaces the history entry; pass "push" to add one
yield* page.remove(); // deletes ?page
yield* Effect.never; // keep the atom alive
}));
Values are stored as JSON. Other query parameters, the hash and history state are preserved. Invalid or repeated values fail creation with UrlAtomError unless options.invalid is "default"; later invalid URLs keep the last valid value and call options.onError.
Islands
| Export | Meaning |
|---|---|
mountIslands(root, registry, onError?, options?) | Mounts every <fuzor-island> below root; resolves to a cleanup function. options: signal, mountTimeoutMs, cleanupTimeoutMs. Used by MPA clients. |
islandErrorHandler | The default error UI with Try again, for onError |
routeParams(element) | Route parameters of the page containing element |
reloadOnStaleDeployment(error) | Reloads once when a chunk from an older build is gone; generated clients use it |
IslandActivationError | Error passed to island error handlers |
Islands also emit a bubbling fuzor:hydration-mismatch event with { island, framework, error } when a preview does not match the browser render; see islands.
An island module exports mount(host, props), which may return a cleanup function or a promise of one, and optionally render(props, { id }) returning HTML or a promise of HTML at build time. See writing an island adapter.
Server data
| Export | Meaning |
|---|---|
routeData(element) | Promise of the server data for the page containing element; shares the page's request |
loadRouteData(outlet, options?) | Starts or restarts the request; options.search, options.fetch |
abortRouteData(outlet) | Cancels a pending request |
fillDataSlots(root, data) | Fills <fuzor-data> slots |
RouteDataError | Failed request, with the HTTP status when there was a response |
See server data.
Navigation adapters
The router picks an adapter automatically: the browser Navigation API where available, the History API elsewhere, and fragment (hash) routing for file: or custom-protocol documents. For tests and non-browser hosts, create one yourself:
import * as Effect from "effect/Effect";
import { createRouter, makeMemoryNavigation } from "fuzor/runtime";
const navigation = await Effect.runPromise(makeMemoryNavigation({ baseUrl: "https://app.test/", initialEntries: [{ href: "/about/" }] }));
const router = createRouter(outlet, { navigation, islands });
| Export | Meaning |
|---|---|
Navigation | The Effect service key for a NavigationAdapter |
makeBrowserNavigation, BrowserNavigationLive, supportsBrowserNavigation, navigationBrowser, navigateDocument | Navigation API adapter and helpers |
makeHistoryNavigation, HistoryNavigationLive | History API adapter |
makeHashNavigation, HashNavigationLive | Fragment adapter for embedded documents |
makeMemoryNavigation, MemoryNavigationLive | In-memory adapter |
makeNavigationCoordinator, coordinateNavigation | Lifecycle orchestration used by the router |
NavigationError, NavigationLifecycleError | Typed adapter and lifecycle failures |
Capacitor integration
import { App } from "@capacitor/app";
import { connectCapacitor, defaultDeepLink } from "fuzor/runtime/capacitor";
// Connects the started SPA router to Capacitor:
const disconnect = await connectCapacitor({
app: App,
rootBack: "exit", // "exit" (default) or "minimize" on the first page
deepLink: defaultDeepLink // optional custom URL mapping
});
| Export | Meaning |
|---|---|
connectCapacitor(options) | Connects deep links (launch URL and appUrlOpen), Android hardware Back button through the router with blockers, and foreground resume to the Fuzor router. Launch URLs are applied once per session so reloads preserve the current page. Resolves to a cleanup function that removes listeners. |
defaultDeepLink(url) | Maps custom schemes (e.g. myapp://about) and App Links (https://...) to app routes. |
URL helpers
routeKey(pathname) and normalizePath(path) apply Fuzor's URL matching rules. normalizeBase, stripBase and withBase convert between app paths and deployment-base paths.