zilk/router

client-side router


Client-side navigation. Automatically intercepts internal <a> links, manages history, and handles dynamic routes.

createRouter({ pull, pages, redirects })

  • pages: { [route_pattern]: {content(), meta(), async [pull]()} }
  • redirects: { [route_pattern]: destination }
  • pull: (default: 'pull') name of optional export to retrieve data for dynamic pages

Available Callbacks

router

  • .performTransition({ meta, content }): required. can only be set once. this is where the main 'routing' logic goes.
  • .onStart(uri):
  • .onBefore({ params, query }): must return true, or routing will abort
  • .onCancel(uri):
  • .onReady({ meta, content }):
  • .onAfter({ meta, content }):
  • .onError(error):

--

Example

router.js

(typically generated programmatically based on files in pages/**.js)

import { createRouter } from 'zilk/router'
import { redirects, setup } from '../pages/_document.js'
import * as $p1 from '../pages/index.js'
import * as $p2 from '../pages/about.js'
let router = createRouter({ pull: 'pull_browser', redirects, pages: {
  '/': $p1,
  '/about': $p2
}})
setup(router)
export { router }

index.html

<head>
  <!-- import the router script -->
  <script src="/router.js" type="module"></script>
</head>
<body>
  <!-- SSR -->
</body>

_document.js

import { html, render } from 'zilk'

export let redirects = {
  '/help': '/docs/help'
}

export function setup(router){
  let root = document.getElementById('root')

  router.performTransition(({ content, meta }) => {
    render(root,content)
    if(meta.title){ document.title = meta.title }
    if(location.hash && location.hash.length > 0){
      const hash = location.hash.substring(1);
      const hashed_element = document.getElementById(hash);
      if (hashed_element) {
        window.scrollTo(0,hashed_element.offsetTop)
      }
    } else {
      window.scrollTo(0,0)
    }
  })

  router.onError((e) => {
    console.log(e)
  })
}

about.js

import { html } from 'zilk'

export let meta = () => ({
  title: "About",
  description: 'About the about',
  uri: 'about',
})

export let content = () => html`
  <h1>About Page</h1>
`