@zoijs/router

A tiny client-side router for single-page apps. Routes are a plain object; links are plain anchors.

npm install @zoijs/core @zoijs/router

Example#

import { html, mount } from "@zoijs/core";
import { createRouter } from "@zoijs/router";

const router = createRouter({
  "/": Home,
  "/about": About,
  "/users/:id": (params) => html`<h1>User ${params.id}</h1>`,
  "*": () => html`<h1>Not Found</h1>`,
});

function App() {
  return html`
    <nav>${router.link("/", "Home")} ${router.link("/about", "About")}</nav>
    ${router.view()}
  `;
}

mount(App, "#app");

A route is pattern: component. A component is a function that returns an html template and receives the matched params.

API#

MemberWhat it does
createRouter(routes, { base })Build a router from a { pattern: component } map
router.view()Render the current page — place it once
router.link(path, text)An <a> that navigates without a reload
router.go(path)Navigate from code
router.path()The current path (reactive)
router.query()The query string as an object (reactive)

Patterns support static segments, dynamic :params, and a "*" not-found route. Static routes win over param routes. The active link gets aria-current="page" automatically.

Hosting under a sub-path#

If your app lives under a sub-path, pass a base so route patterns stay clean:

createRouter(routes, { base: "/app" });
This very site uses the router. A hard refresh of a deep link needs a server fallback — see Deployment.

Known limitations#

  • History mode only (deep-link refreshes need a server SPA fallback).
  • No nested-outlet system, route guards, or loaders — by design.
  • No SSR.