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

@homer0/routes-manager

v3.0.8

Published

Create and manage a collection of typed routes for your app

Downloads

18

Readme

🚏 Routes manager

Create and manage a collection of typed routes for your app.

The main feature of this library is the typing, as it will auto complete the names and the parameters of the routes.

🍿 Usage

⚙️ Setup

You first needs to create an instance of the manager with the routes definitions:

// routes.ts

import { createRoutesManager } from '@homer0/routes-manager';

export const routes = createRoutesManager({
  // You always need a `root` for a group of routes.
  root: '/',
  // A route can be just a string,
  home: '/',
  // or an object with more details,
  login: {
    path: '/login',
    optionalQueryParams: ['redirectTo'],
  },
  // or a sub group of routes.
  account: {
    // A sub group also needs a `root`.
    root: '/account',
    home: '/',
    settings: {
      root: '/settings',
      connection: '/connections/:connectionId',
      removeMe: {
        path: '/remove-account',
        queryParams: ['confirm'],
      },
    },
  },
});

After that, you can use the instance to generate paths:

// some-other-file.ts

import { routes } from './routes';

// It won't ask for parameters and will return '/'
const homeRoute = routes.getPath('home');
// It won't ask for parameters and will return '/login'
const loginRoute = routes.getPath('login');
// You can optional send the `redirectTo` parameter and will return '/login?redirectTo=/account'
const loginRouteWithRedirect = routes.getPath('login', {
  redirectTo: routes.getPath('account.home'),
});
// It will ask for `connectionId` and will return `/account/settings/connections/123`
const connectionRoute = routes.getPath('account.settings.connection', {
  connectionId: '123',
});
// You can also send unknown parameters, and it will add them in the query string.
// In this case, it will return `/account/settings/connections/123?foo=bar`
const connectionRouteWithFoo = routes.getPath('account.settings.connection', {
  connectionId: '123',
  foo: 'bar',
});

🛤️ Defining a route

A route can be defined as a string that starts with a /, or as an object with the following properties:

import { createRoutesManager } from '@homer0/routes-manager';

export const routes = createRoutesManager({
  root: '/',
  // Simple string route
  home: '/',
  // String route with parameters
  category: '/category/:categoryId',
  // Object route
  login: {
    // The path of the route.
    path: '/login',
    // Optional query parameters.
    optionalQueryParams: ['redirectTo'],
    // Required query parameters.
    queryParams: ['token'],
  },
  // Object route with parameters
  tag: {
    // The path of the route.
    path: '/tags/:tagId',
    // Optional query parameters.
    optionalQueryParams: ['page'],
    // Required query parameters.
    queryParams: ['sort'],
  },
});

If a route has parameters in its path or it defines queryParams, the second argument of the getPath method will be required, but if it doesn't, it will be optional, with types for optionalQueryParams, if present.

⚡️ Using groups

Groups allow you to create a collection of routes under a common root, and better organize your routes. When creating your routes definition, adding a group is as simple as adding an object with a root property:

import { createRoutesManager } from '@homer0/routes-manager';

export const routes = createRoutesManager({
  root: '/',
  home: '/',
  category: '/category/:categoryId',
  // A group of routes.
  tags: {
    root: '/tags',
    // A route inside the group.
    view: '/:tagId',
  },
});

All routes in a group are prefixed by the group's root and the parent group's root: As you may have noticed already, the definition's root is just another group.

When accessing a route in a group, you'll need to use the group name as a prefix, so the getPath method will look like this:

routes.getPath('tags.view', {
  tagId: '123',
});

And yes, everything is typed and auto-completed even in sub groups/routes.

You could also use parameters in a group's root, and all its routes (and possible sub groups' routes) will inherit them:

import { createRoutesManager } from '@homer0/routes-manager';

export const routes = createRoutesManager({
  root: '/',
  home: '/',
  category: '/category/:categoryId',
  tag: {
    root: '/tags/:tagId',
    // A route inside the group.
    view: '/view',
    manage: {
      root: '/manage',
      // A route inside a sub group.
      edit: '/edit',
    },
  },
});

If we look at the tag group, you'll need to send the tagId parameter to access any of its routes:

const viewTagRoute = routes.getPath('tag.view', {
  tagId: '123',
});
const editTagRoute = routes.getPath('tag.manage.edit', {
  tagId: '123',
});

🤘 Development

As this project is part of the packages monorepo, some of the tooling, like lint-staged and husky, are installed on the root's package.json.

Tasks

| Task | Description | | ------------- | ----------------------------------- | | lint | Lints the package. | | test | Runs the unit tests. | | build | Transpiles and bundles the project. | | types:check | Validates the TypeScript types. |

Motivation

I always liked the idea of using named routes in an app, rather than harcoded strings, but most of the solutions I found were not strongly typed, or were connected to a specific framework/routing library; I just wanted to define my routes, call them by name, and get auto-completion.