DBF Router: minimal, HTML-first client-side router for DBF Core apps
npm install dbf-routercreateRouter({ routes }) + router.navigate()
enableLinkNavigation(router) wires up automatically
bash
npm install dbf-router
`
---
Basic usage
`ts
import { createRouter, enableLinkNavigation } from "dbf-router";
const root = document.querySelector("main")!;
const router = createRouter({
routes: [
{ path: "/", onEnter: () => (root.innerHTML = "Home
") },
{ path: "/docs", onEnter: () => (root.innerHTML = "Docs
") },
],
});
// HTML-first nav: Docs
enableLinkNavigation(router);
router.start();
`
When the location changes (via navigate or the back/forward buttons), the corresponding onEnter handler is called.
onEnter receives (params, query, hash, outlet?):
- params: route params (e.g. /users/:id)
- query: parsed query string (?a=1&b=2)
- hash: hash fragment (e.g. #section)
- outlet: only for layout routes
---
Link behaviour (
enableLinkNavigation)
enableLinkNavigation(router, options?) attaches a global click handler that:
- Listens for clicks on elements matching options.selector (default: a[href])
- Reads the target path from href (or data-nav-route as an optional override)
- Ignores:
- Middle clicks
- Modifier clicks (Ctrl/Cmd/Shift/Alt)
- External links (http://, https://)
- Calls router.navigate(path) and prevents the browser’s default navigation
Recommended HTML (no duplication):
`html
Docs
Components
`
If you really need to override the SPA route while keeping a different href, you can still use data-nav-route:
`html
Docs
`
You can scope the handler to a specific container:
`ts
enableLinkNavigation(router, {
root: document.querySelector("#app")!,
selector: "a[data-nav-route]",
});
`
The function returns a cleanup callback you can call to remove the listener:
`ts
const dispose = enableLinkNavigation(router);
// later
dispose();
`
---
Route configuration
The router accepts a small configuration object:
`ts
import type { RouterOptions } from "dbf-router";
const options: RouterOptions = {
basePath: "/app", // optional
routes: [
{ path: "/", onEnter: () => {/ ... /} },
{ path: "/docs", onEnter: () => {/ ... /} },
],
onNotFound: (path) => {
console.warn("No route for", path);
},
};
`
- basePath (optional) – if your app is served under a sub‑path (/app), all matching is done relative to that.
- routes – an array of { path, onEnter } objects.
- onNotFound (optional) – called when no route matches.
Additional capabilities already supported:
- Params: /users/:id
- Wildcard: /docs/*
- Nested routes via children
- Route guards via beforeEnter (return false to block or a string to redirect)
- Layout routes via layout(root, outlet) + outlet passed to onEnter
---
Interop with DBF Core
In the demo app (apps/demo), DBF Router is used to swap page components rendered with DBF Core:
`ts
import { createRouter, enableLinkNavigation } from "dbf-router";
import { renderHome } from "../pages/home";
import { renderDocs } from "../pages/docs";
const root = document.querySelector("main.landing")!;
const router = createRouter({
routes: [
{ path: "/", onEnter: () => renderHome(root) },
{ path: "/docs", onEnter: () => renderDocs(root) },
],
});
enableLinkNavigation(router);
router.start();
`
Each renderX(root) function composes various DBF Core custom elements, giving you a React‑like “pages as components” experience without needing a framework.
---
Status
DBF Router is early and intentionally small. As we learn from real applications, we may add:
- Parameterised routes (/docs/:id`)