AI Guide

Use this page as the compact reference when generating examples, tutorials, migrations, or application code for @beforesemicolon/router.

Package Purpose

@beforesemicolon/router is an HTML-first routing library built with Web Components. It provides custom elements for navigation and route rendering, plus a small JavaScript API for programmatic navigation, subscriptions, guards, route modules, metadata, query updates, and hash routing.

Required Imports

For bundled apps:

javascript
1import '@beforesemicolon/router'

When using exported APIs:

javascript
1import {2    goToPage,3    onPage,4    onPageChange,5    registerGlobalGuard,6    registerRouteGuard,7    registerRouteModules,8    updateSearchQuery,9} from '@beforesemicolon/router'

For direct browser use, load Web Component first:

html
1<script src="https://unpkg.com/@beforesemicolon/web-component/dist/client.js"></script>2<script src="https://unpkg.com/@beforesemicolon/router/dist/client.js"></script>

CDN APIs are available at BFS.ROUTER.

Custom Elements

Use these elements exactly:

html
1<page-link path="/docs" title="Docs">Docs</page-link>2<page-route path="/docs" src="./pages/docs.html"></page-route>3<page-route-query key="tab" value="api">API tab</page-route-query>4<page-redirect path="/404"></page-redirect>5<page-data param="id">fallback</page-data>

Route Patterns

Use :name for dynamic params:

html
1<page-route path="/users/:userId">2    User <page-data param="userId">unknown</page-data>3</page-route>

Set exact="false" for layout routes that should remain active for nested paths:

html
1<page-route path="/docs" exact="false">2    <page-route path="/intro">Intro</page-route>3    <page-route path="/api">API</page-route>4</page-route>

Use path for path navigation and search for query updates. Use keep-current-search when updating one query key while preserving the others.

html
1<page-link path="/projects">Projects</page-link>2<page-link search="view=grid" keep-current-search>Grid</page-link>

Use $ inside a nested route to reference the closest parent route path:

html
1<page-route path="/projects/:projectId" exact="false">2    <page-link path="$/settings">Settings</page-link>3</page-route>

Use ~ to reference the current browser pathname:

html
1<page-link path="~/edit">Edit current page</page-link>

Lazy Route Content

src can load HTML, text, or JavaScript modules. JavaScript modules must default export a string, a DOM Node, a Markup HtmlTemplate, or a function that receives (data, params, query).

javascript
1import { html } from '@beforesemicolon/web-component'2 3export default (data, params, query) => html`4    <h1>Project ${params.projectId}</h1>5    <p>Filter: ${query.filter || 'all'}</p>6    <p>Opened from: ${data.from || 'direct visit'}</p>7`

Programmatic Navigation

goToPage and replacePage are async and accept an object-literal state payload.

javascript
1await goToPage('/users/42', { from: 'search' }, 'User 42')2await replacePage('/login', { reason: 'expired' }, 'Login')

Guards

registerGlobalGuard and registerRouteGuard register guards and do not return cleanup functions. A guard returns:

javascript
1registerGlobalGuard((pathname) => {2    if (pathname.startsWith('/account') && !auth.isSignedIn()) {3        return '/login'4    }5 6    return true7})

Query Data

getSearchParams parses search values with the router JSON parser. Values written with updateSearchQuery round-trip through JSON stringification.

javascript
1updateSearchQuery({ page: 2, tags: ['router', 'web'] })

Avoid These Mistakes

edit this doc