npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@phcdevworks/spectre-shell-router

v0.0.1

Published

Minimal, framework-agnostic client-side router for vanilla TypeScript apps.

Downloads

85

Readme

@phcdevworks/spectre-shell-router

A minimal, framework-agnostic client-side router for vanilla TypeScript apps. Designed to support the Spectre platform's app shell with simple URL-to-page mapping and lifecycle management.

🤝 Contributing Guide | 📝 Changelog

Overview

@phcdevworks/spectre-shell-router is not a full routing framework. It intentionally solves one problem: mapping URLs to page modules and managing page lifecycle in a vanilla web app.

  • ✅ Maps URL paths to async page module loaders
  • ✅ Supports path parameters (e.g., /users/:id)
  • ✅ Uses the browser History API (pushState, popstate)
  • ✅ Loads pages dynamically via import()
  • ✅ Calls page render(ctx) and optional destroy() lifecycle hooks
  • ✅ Minimal surface area—easy to delete or replace

Installation

npm install @phcdevworks/spectre-shell-router

Usage

1. Define Your Routes

import { Router } from '@phcdevworks/spectre-shell-router'

const routes = [
  { path: '/', loader: () => import('./pages/home') },
  { path: '/users/:id', loader: () => import('./pages/user') },
  { path: '/about', loader: () => import('./pages/about') },
]

const router = new Router(routes, document.getElementById('app'))

2. Create Page Modules

Each page module must export a render function:

// pages/user.ts
export function render(ctx: RouteContext) {
  const userId = ctx.params.id
  ctx.root.innerHTML = `<h1>User ${userId}</h1>`
}

export function destroy() {
  // Optional cleanup
  console.log('Leaving user page')
}

3. Navigate

// Programmatic navigation
router.navigate('/users/123')

// Or use standard links with History API interception
<a href="/about">About</a>

Page Contract

Each page module must export:

export function render(ctx: RouteContext): void
export function destroy?(): void  // optional

Where RouteContext contains:

  • path – the matched URL path
  • params – route parameters (e.g., { id: '123' })
  • query – URLSearchParams object
  • root – the DOM element where the page should render

What It Does

✅ Maps URL paths to page loaders
✅ Path parameter extraction (/users/:id)
✅ History API integration
✅ Dynamic page imports
✅ Lifecycle hooks (render, destroy)

What It Does NOT Do

❌ No nested routing
❌ No layouts or middleware
❌ No guards or data fetching
❌ No global state management
❌ No SSR or hydration
❌ No transitions or animations
❌ No framework lifecycle integration

Development Philosophy

This router follows a minimal by design approach:

1. Core Routing

Purpose: Map URLs to pages and manage lifecycle

Rules:

  • Keep the API surface minimal and predictable
  • No framework dependencies or assumptions
  • Router only maps paths and manages lifecycle
  • TypeScript strict mode with proper type exports

2. Page Contract

Purpose: Simple interface for pages to integrate

Contains:

  • render(ctx) - Required page entry point
  • destroy() - Optional cleanup handler
  • RouteContext - Type-safe context object

Rules:

  • Pages handle their own rendering
  • No magic or hidden behavior
  • Clear separation of concerns

Golden Rule (Non-Negotiable)

Routing should be boring, small, explicit, and replaceable.

This router exists to define a navigation and page lifecycle contract, not to compete with full-featured frameworks.

Design Principles

  1. Minimal surface area - Only essential routing features
  2. Framework-agnostic - Works with any rendering approach
  3. Type-safe - Full TypeScript support with proper exports
  4. Disposable by design - Easy to replace if a framework is adopted later
  5. Production-ready - Simple, tested, and reliable

TypeScript Support

Full TypeScript definitions are included:

import type { Router, RouteContext, Route } from '@phcdevworks/spectre-shell-router'

Part of the Spectre Suite

  • Spectre Tokens - Design token foundation
  • Spectre UI - Core styling layer
  • Spectre Shell Router - Client-side routing (this package)
  • Spectre Shell - Application shell framework
  • Spectre Blocks - WordPress block library
  • Spectre Astro - Astro integration

Contributing

Issues and pull requests are welcome. For detailed contribution guidelines, see CONTRIBUTING.md.

License

MIT © PHCDevworks — See LICENSE for details.


❤️ Support Spectre

If Spectre Shell Router helps your workflow, consider sponsoring: