Navigation

navLink() is the next/link equivalent — a patch for native a elements:

import { navLink } from "@domphy/app"
import { link } from "@domphy/ui"

{
  a: "Blog",
  $: [link(), navLink({ href: "/blog" })],
}

It intercepts plain left-clicks for client navigation (modified clicks, target="_blank", downloads and external origins fall through to the browser), prefetches, and exposes active state:

  • aria-current="page" and data-active are set reactively while the link matches the current pathname (descendant paths count unless exact: true)
  • style the active state with a selector: style: { "&[data-active]": { ... } }

Props:

PropDefaultMeaning
hrefrequiredtarget path
prefetch"hover""hover", "visible" (IntersectionObserver) or false
replacefalsereplace the history entry
scrolltruescroll to top (or #hash) after navigating
exactfalseactive only on exact pathname match
routerapp routerexplicit router instance

The Router

app.router is the useRouter() equivalent:

const router = app.router

router.push("/blog/hello")        // navigate, push history
router.replace("/login")          // navigate, replace history
router.back()                     // history back
router.forward()                  // history forward
router.refresh()                  // clear loader cache, re-render current URL
router.prefetch("/blog/hello")    // run loaders ahead of navigation

push/replace resolve relative hrefs against the current URL and hand off external origins to the browser.

The next/router events equivalent:

const release = router.addEventListener("routeChangeStart", (href) => {
  console.log("navigating to", href)
})

router.addEventListener("routeChangeComplete", (href) => { ... })
router.addEventListener("routeChangeError", (error, href) => { ... })

release() // unsubscribe

Scroll Behavior

The router manages scrolling like Next.js: scroll to top after navigation, scroll to the #hash element when present, and restore the saved position on back/forward. Pass scroll: false to navigate/push/navLink to opt out.

History Modes

By default the router binds to the browser history. For tests, embedded demos or custom hosts, pass a memory history:

import { createApp, createMemoryHistory } from "@domphy/app"

const app = createApp(routes, { history: createMemoryHistory("/start") })

history: null disables history entirely (used internally for SSR).