TypeScript icon, indicating that this package has built-in type declarations

3.2.35 • Public • Published


npm version npm downloads Mastodon Follow

This project is part of the @thi.ng/umbrella monorepo and anti-framework.


Generic router for browser & non-browser based applications.

  • Declarative route definitions
  • Parametric routes, each param with optional value coercion & validation
  • Route authentication handler to enable/disable routes based on other state factors
  • Fallback route
  • Enforced initial route (optional)
  • Route formatting (with params)
  • HTML5 history & hash fragment support

Partially based on the Clojure implementation in thi.ng/domus.


STABLE - used in production

Search or submit any issues for this package

Related packages

  • @thi.ng/hdom - Lightweight vanilla ES6 UI component trees with customizable branch-local behaviors
  • @thi.ng/rdom - Lightweight, reactive, VDOM-less UI/DOM components with async lifecycle and @thi.ng/hiccup compatible


yarn add @thi.ng/router

ES module import:

<script type="module" src="https://cdn.skypack.dev/@thi.ng/router"></script>

Skypack documentation

For Node.js REPL:

const router = await import("@thi.ng/router");

Package sizes (brotli'd, pre-treeshake): ESM: 1.38 KB


Usage examples

Several demos in this repo's /examples directory are using this package.

A selection:

Screenshot Description Live demo Source
Complete mini SPA app w/ router & async content loading Demo Source


Generated API docs

import { HTMLRouter, EVENT_ROUTE_CHANGED } from "@thi.ng/router";

// router configuration
const config = {

    // use hash fragment for routes
    useFragment: true,

    // fallback route (when no other matches)
    defaultRouteID: "home",

    // optional enforced route when router starts
    initialRouteID: "home",

    // Optional route path component separator. Default: `/`
    separator: "/",

    // Route prefix. Default: `/` (or `#/` if `useFragment` is enabled).
    // All routes to be parsed by `route()` are assumed to have this prefix.
    // All routes returned by `format()` will include this prefix.
    prefix: "#/",

    // actual route defs
    // these are checked in given order
    // IMPORTANT: rules with common prefixes MUST be specified in
    // order of highest precision / longest path
    routes: [
            // each route MUST have an ID
            id: "home",
            // optional title for UI purposes (no internal function)
            title: "Home page",
            // this array defines the route path items
            match: ["home"]
            id: "user-profile",
            // this rule is parametric
            // variable items are prefixed with `?`
            match: ["users", "?id"],
            // coercion & validation handlers for "?id" param
            // coercion fn is applied BEFORE validator
            validate: {
                id: {
                    coerce: (x) => parseInt(x),
                    check: (x)=> x > 0 && x < 100
            id: "image",
            // this route has 2 params and matches (for example):
            // "/images/07a9d87b-c07a-42e3-82cf-baea2f94facc/xl"
            match: ["images", "?id", "?size"],
            validate: {
                id: {
                    check: (x)=> isUUID(x)
                size: {
                    check: (x)=> /^(s|m|l|xl)$/.test(x)
            // enable auth for this route
            // (see info about authenticator functions below)
            auth: true
            id: "group-list",
            // matches only: "/users" or "/images"
            match: ["?type"],
            validate: {
                type: {
                    check: (x) => /^(users|images)$/.test(x)
            auth: true

// `HTMLRouter` ONLY works in browser environments
// for non-browser use cases use `BasicRouter`
const router = new HTMLRouter(config);
router.addListener(EVENT_ROUTE_CHANGED, console.log);



If this project contributes to an academic publication, please cite it as:

  title = "@thi.ng/router",
  author = "Karsten Schmidt",
  note = "https://thi.ng/router",
  year = 2014


© 2014 - 2023 Karsten Schmidt // Apache License 2.0


DownloadsWeekly Downloads






Unpacked Size

46.6 kB

Total Files


Last publish


  • thi.ng