@aegisjsproject/atlas
v1.0.2
Published
A client-side router library using `Navigation` & `URLPattern`
Maintainers
Readme
@aegisjsproject/atlas
A client-side router library using Navigation & URLPattern
Overview
This router intercepts same-origin navigations and resolves them to registered route modules. Each module can return content in multiple native formats (e.g. Response, Document, Element), allowing flexibility without imposing rendering constraints.
Key characteristics:
- Native Navigation API (
navigation) - Route-to-module mapping via dynamic
import() - Direct DOM updates (no diffing layer)
- Supports HTML streaming via
Response - Built-in metadata handling (title, description, styles)
- Optional preload observation
- Abort-safe lifecycle with
AbortControllerandDisposableStack
[!IMPORTANT] This requires the Navigation API, which is Baseline 2026. It also creates a Trusted Types Policy, where supported, labeled
"aegis-atlas#html"for handling HTML responses without sanitizer restrictions.
[!TIP] Route module specifiers can use bare specifiers like
@acme/blog. These can be resolved via an import map, for example:<script type="importmap"> { "imports": { "@acme/blog": "https://cdn.example.com/acme-blog/index.js" } } </script>This allows modules to be loaded from a CDN without changing route definitions.
Installation
This module is intended to be used directly in modern browser environments.
import { init } from '@aegisjsproject/atlas';No dependencies required.
Core Concepts
Route Modules
Each route resolves to a module with the following shape:
export default async function handler(request, context) {
return new Response('<h1>Hello</h1>', {
headers: { 'Content-Type': 'text/html' }
});
}
export const title = 'Page Title';
export const description = 'Page description';
export const styles = new CSSStyleSheet();Supported Exports
default(required)- Function:
(Request, RouteContextObject) => HandlerResult - Or static value:
HandlerResult
- Function:
title(optional)description(optional)styles(optional:CSSStyleSheetor array)
Handler Return Types
Handlers may return:
Response(must betext/html)HTMLDocumentElementDocumentFragmentURL(triggers navigation)
Route Context
Each handler receives a context object:
{
result, // URLPatternResult
params, // extracted route params
stack, // DisposableStack
controller, // AbortController
signal, // AbortSignal
type, // navigation type
url, // URL instance
state, // navigation state
info, // navigation info
timestamp // performance timestamp
}
Usage
Initialize Router
init({
'/': '/routes/home.js',
'/users/:id': '/routes/user.js'
'/posts/:year(\\d{4})/:month(\\d{2})/:day(\\d{2})/:slug': '@acme/blog',
'/product/:sku': '@acme/store/product',
}, {
root: 'app',
preload: true
});
Options
root: Element or element ID where content is renderedpreload: Enable preload observationsignal: OptionalAbortSignalfor teardown
Navigation Helpers
import { navigate, back, forward, reload } from './router.js';
navigate('/about');
back();
forward();
reload();Navigation Lifecycle
Wait for navigation completion:
import { whenLoaded } from './router.js';
await whenLoaded();Behavior Details
Interception Rules
Navigation is intercepted only if:
event.canInterceptis true- URL is same-origin
- Triggering element does not have
.no-router
Content Handling
Response
- Must be
text/html - Parsed via
Document.parseHTMLUnsafe - Re-processed as
HTMLDocument
HTMLDocument
- Updates:
document.title- meta description
- root content
Element / DocumentFragment
- Directly replaces root children
URL
- Triggers navigation
Root Management
setRoot('app');
// or
setRoot(document.getElementById('app'));
If root is <body>, full body is replaced.
If root is an element with id, only matching subtree is replaced.
Metadata Updates
Route modules can define:
title→ updatesdocument.titledescription→ updates all matching meta tags:name="description"og:descriptiontwitter:description
styles→ appended todocument.adoptedStyleSheets
Form Handling
- Automatically determines method (
GETorPOST) - Submits
FormDatawhen applicable - Uses
RequestAPI for consistency
Abort + Cleanup
Each navigation:
- Uses
AbortController - Combines signals via
AbortSignal.any - Cleans up via
DisposableStack
Handlers should respect context.signal where applicable.
Trusted Types
If supported, a Trusted Types policy is used to safely pass HTML into:
Document.parseHTMLUnsafe(...)
This ensures CSP compatibility without stripping critical markup like:
<iframe>- inline event handlers
- form attributes
Example Route
export default async function(request, { params }) {
return new Response(`
<h1>User ${params.id}</h1>
`, {
headers: { 'Content-Type': 'text/html' }
});
}
export const title = 'User Profile';
export const description = 'User details page';
Notes
- Only
text/htmlresponses are supported forResponse - Non-matching routes fall back to
fetch() - Errors during routing are surfaced via
reportError - Designed for modern browsers with Navigation API support
Summary
This router provides a low-level, high-control alternative to framework routers by:
- Eliminating abstraction layers
- Leveraging native platform APIs
- Supporting flexible content types
- Maintaining strict control over navigation lifecycle
Intended for environments where performance, control, and minimal overhead are priorities.
