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

@stackra/routing

v2.0.0

Published

Client-side routing for the Stackra framework — guards, middleware, SEO, analytics, breadcrumbs, route modes (page/dialog/drawer/sheet), advanced matchers (subdomain/query/header/hash), and a `defineRoute()` builder that composes with React Router v7.

Downloads

363

Readme

@stackra/routing

Client-side routing for the Stackra framework — guards, middleware, SEO, analytics, breadcrumbs, route modes (page / dialog / drawer / sheet), advanced matchers (subdomain / query / header / hash), a defineRoute() builder that composes with React Router v7, and two auto-discovery paths that eliminate the RoutingModule.forFeature({ routes }) boilerplate that used to live in every Web<Pkg>Module.

Auto-discovery — two paths

Every route in a Stackra app takes one of three shapes today. Pick per file based on what the file needs:

Shape 1 — @Route class (framework packages that need DI). The class extends BaseRoute, injects whatever config / flags / services the route needs, and returns the record from getRecord():

// packages/frontend/rbac/src/react/routes/roles-list/roles-list.route.tsx
import { BaseRoute } from "@stackra/routing";
import { Route } from "@stackra/decorators/routing";
import { Inject } from "@stackra/container";
import { RBAC_CONFIG } from "@stackra/contracts";

@Route({ id: "rbac.roles-list", source: "rbac" })
export class RolesListRoute extends BaseRoute {
  public constructor(
    @Inject(RBAC_CONFIG) private readonly config: IRbacConfig,
  ) {
    super();
  }
  public getRecord() {
    return { path: this.config.routePaths.rolesList, Component: RolesListPage };
  }
}

The class lands in the package's Web<Pkg>Module.forRoot() providers array; the RouteLoader walks the DI graph at OnApplicationBootstrap and auto-registers every @Route-decorated class into the RouteRegistry. No RoutingModule.forFeature(...) call needed.

Shape 2 — file-based via the Vite collectRoutes plugin (app-level routes). For app-level static routes that don't need DI. Each route file just exports a default record:

// apps/dashboard/src/routes/some-page.route.tsx
import { defineRoute } from "@stackra/routing";
export default defineRoute({ path: "/some-page", Component: SomePage });

Enable the collector in the app's vite.config.ts:

import { router } from "@stackra/routing/vite";

export default defineConfig({
  plugins: [
    router({
      collectRoutes: { globs: ["src/routes/**/*.route.tsx"] },
    }),
  ],
});

Then feed the collected list into the routing module:

// apps/dashboard/src/main.tsx (or app.module.ts)
import collectedRoutes from "virtual:stackra-routing/collected-routes";
import { RoutingModule } from "@stackra/routing";

@Module({
  imports: [RoutingModule.forRoot({ basename: "/", routes: collectedRoutes })],
})
export class AppModule {}

Add the ambient module type in apps/<name>/src/vite-env.d.ts:

/// <reference types="@stackra/routing/client" />

Shape 3 — plain records + RoutingModule.forFeature({ routes }). Legacy. Still supported for backward compat; new code should pick Shape 1 or 2.

Which shape to pick

  • Framework package (@stackra/rbac, @stackra/grants, ...) whose route path depends on injected config → Shape 1.
  • App-level static route with no DI need → Shape 2.
  • Existing code that already works → leave alone.

Phase F.1 — core. This release ships the non-React CORE only. The React subpath (@stackra/routing/react) lands in F.2; the Vite plugin (@stackra/routing/vite) lands in F.3. Every symbol below is framework-agnostic and safe to import from a Node build script or a browser bundle alike.

Install

pnpm add @stackra/routing @stackra/container @stackra/contracts @stackra/decorators \
  @stackra/error @stackra/events @stackra/logger @stackra/pipeline @stackra/support \
  react-router reflect-metadata

Quick start (F.1 surface)

import { Module } from "@stackra/container";
import {
  RoutingModule,
  defineRoute,
  defineLayout,
  definePage,
} from "@stackra/routing";
import { subdomain, query } from "@stackra/routing/matchers";
import { organization, article } from "@stackra/routing/seo";

@Module({
  imports: [
    RoutingModule.forRoot({
      basename: "/",
      rootDomain: "figentra.com",
      seo: {
        baseUrl: "https://figentra.com",
        defaults: {
          jsonLd: [
            organization({ name: "Stackra", url: "https://figentra.com" }),
          ],
        },
      },
    }),
  ],
})
export class AppModule {}

Native usage (@stackra/routing/native)

The native subpath ships the React Navigation v7 counterpart to the web subpath. defineScreen() mirrors defineRoute(), and <StackraNativeRoutingProvider> composes <NavigationContainer> with a LinkingOptions config auto-built from every screen's path field.

Install the native peers alongside the routing package:

pnpm add @react-navigation/native @react-navigation/native-stack \
  react-native-screens react-native-safe-area-context

Wire it in the app module + provider stack:

// src/config/routing.config.ts
import { registerAs } from "@stackra/config";
import { defineScreen } from "@stackra/routing/native";
import type { INativeRoutingModuleOptions } from "@stackra/contracts";

import { HomeScreen } from "@/screens/home.screen";
import { SettingsScreen } from "@/screens/settings.screen";

export const routingConfig = registerAs<INativeRoutingModuleOptions>(
  "routing",
  () => ({
    initialRouteName: "Home",
    screens: [
      defineScreen({ name: "Home", component: HomeScreen, path: "" }),
      defineScreen({
        name: "Settings",
        component: SettingsScreen,
        path: "settings",
      }),
    ],
    linking: {
      enabled: true,
      prefixes: ["stackra://", "https://app.stackra.com"],
    },
  }),
);
// src/app.module.ts
import { Module } from "@stackra/container";
import { ConfigModule } from "@stackra/config";
import { NativeRoutingModule } from "@stackra/routing/native";
import { routingConfig } from "@/config/routing.config";

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true, load: [routingConfig] }),
    NativeRoutingModule.forRoot(routingConfig()),
  ],
})
export class AppModule {}
// App.tsx
import "reflect-metadata";
import { ApplicationFactory } from "@stackra/container";
import { ContainerProvider } from "@stackra/container/react";
import { StackraNativeRoutingProvider } from "@stackra/routing/native";
import { AppModule } from "@/app.module";
import { RootNavigator } from "@/navigation/root-navigator";

export default function App() {
  const app = ApplicationFactory.create(AppModule);
  return (
    <ContainerProvider context={app}>
      <StackraNativeRoutingProvider>
        <RootNavigator />
      </StackraNativeRoutingProvider>
    </ContainerProvider>
  );
}
// src/navigation/root-navigator.tsx
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { useStackraNativeRouting } from "@stackra/routing/native";

const Stack = createNativeStackNavigator();

export function RootNavigator() {
  const { screens, config } = useStackraNativeRouting();
  return (
    <Stack.Navigator initialRouteName={config.initialRouteName}>
      {screens.map((screen) => (
        <Stack.Screen
          key={screen.name}
          name={screen.name}
          component={screen.component}
          options={screen.options}
          initialParams={screen.initialParams}
        />
      ))}
    </Stack.Navigator>
  );
}

The provider iterates the registry as the single source of truth — adding a screen means editing routing.config.ts only; the navigator picks it up without a code change.

Subpaths

| Import | Purpose | | --------------------------- | ---------------------------------------------------------------------------------------------------------- | | @stackra/routing | Core module + services (registry, matcher, middleware/guard resolvers, SEO) | | @stackra/routing/matchers | Callable matcher builders — subdomain, query, header, hash | | @stackra/routing/seo | JSON-LD builders (article, organization, faqPage, …) | | @stackra/routing/rrv7 | Type-only re-exports of RRv7 primitives (IRrvRouteObject, …) | | @stackra/routing/native | React Navigation v7 bindings — defineScreen, <StackraNativeRoutingProvider>, useStackraNativeRouting | | @stackra/routing/testing | Unit-test helpers (createMockGuardContext, runGuard, …) |

What's coming later

  • F.2 — React subpath. <Link>, useNavigate(), <SeoHead />, <StackraRoutingProvider>, <OverlayOutlet />, <Breadcrumbs />, dev-tools panel.
  • F.3 — Vite plugin. router() plugin for dev subdomain wiring, build-time prerender pipeline, subdomain output split.
  • G — AI integration. <AiRouteContext> + navigateTool binding.
  • Native follow-ups. NativeRoutingModule.forFeature({ name, screens }) for cross-package screen contributions; Liquid Glass tabs via Callstack's @bottom-tabs/react-navigation — both deferred to follow-up specs.

License

MIT