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

routerino

v2.6.3

Published

The React router that Google can read. Built-in SSG, meta tags, sitemaps, and canonical URLs — zero dependencies, no framework lock-in.

Readme

Routerino — The React router that Google can read.

React routing with built-in SEO. No framework, no lock-in.

Live demos: raymondsseptic.com · kissimmeekastawayvilla.com · nerdswithkeyboards.com · logbook-ed.com


Why

React SPAs are fast for users but invisible to search engines. The standard answer — Next.js or Remix — forces a full framework adoption, new conventions, and vendor lock-in for what should be a solved problem: generating static HTML with proper meta tags at build time.

Routerino gives you that. Zero added dependencies, standard <a> tags, and a Vite plugin that generates complete static HTML including meta tags, Open Graph tags, canonical URLs, sitemap.xml, and robots.txt. You keep your SPA developer experience. Google gets readable pages.

Quick Start

npm i routerino
import Routerino from "routerino";

export const routes = [
  {
    path: "/",
    element: <p>This is the home page!</p>,
    title: "My Home Page!",
    description: "Welcome to my home page!",
  },
  {
    path: "/blog/my-first-post/",
    element: (
      <article>
        <h1>My First Post</h1>
        <p>Lorem ipsum...</p>
      </article>
    ),
    title: "My First Post",
    description: "The first post on my new home page!",
    tags: [{ property: "og:type", content: "article" }],
  },
];

<Routerino title="Example.com" routes={routes} />;

What It Does

| Feature | Routerino | React Router | Next.js | Gatsby | Remix | | ---------------------- | ----------------------- | -------------------- | -------------------- | -------------------- | -------------------- | | SSG (static HTML) | ✅ Built-in Vite plugin | ❌ | ✅ Built-in | ✅ Core feature | ✅ Built-in | | Meta tags / Open Graph | ✅ Per-route, automatic | ❌ | ✅ Metadata API | ✅ Via plugin | ✅ meta export | | Sitemap generation | ✅ Automatic | ❌ | ❌ Manual | ✅ Via plugin | ❌ Manual | | Canonical URLs | ✅ Automatic | ❌ | ❌ Manual | ❌ Manual | ❌ Manual | | Standard <a> tags | ✅ No <Link> needed | ❌ Must use <Link> | ❌ Must use <Link> | ❌ Must use <Link> | ❌ Must use <Link> | | Runtime dependencies | 0 (peer: react) | 3+ | 50+ | 100+ | 20+ | | Prerender support | ✅ Built-in | ❌ | ✅ ISR | ✅ SSG | ✅ Built-in | | Library, not framework | ✅ | ✅ | ❌ | ❌ | ❌ |

Installation

npm i routerino

Routerino requires React, React DOM, and PropTypes as peer dependencies (typically already installed). Supports React 18/19 and Node.js 18+.

Usage

Route Configuration

Routes are plain objects. At minimum, each needs a path and element:

export const routes = [
  {
    path: "/",
    element: <HomePage />,
    title: "Home",
    description: "Welcome to our site",
  },
  {
    path: "/about/",
    element: <AboutPage />,
    title: "About Us",
    description: "Learn more about our team",
    imageUrl: "/images/about-og.jpg",
  },
  {
    path: "/products/:id/", // dynamic route — not statically generated
    element: <ProductPage />,
  },
];

Links are standard <a> tags. Routerino intercepts same-origin clicks for SPA navigation; the browser handles everything else (cross-origin links, mailto:, target="_blank", file downloads, etc.) automatically.

The useRouterino Hook

Access router state from any component:

import { useRouterino } from "routerino";

function ProductPage() {
  const { currentRoute, params, routePattern, updateHeadTag } = useRouterino();

  useEffect(() => {
    updateHeadTag({ name: "description", content: `Product: ${params.id}` });
  }, [params.id]);

  return <div>Product: {params.id}</div>;
}

Returns: currentRoute, params, routePattern, updateHeadTag

updateHeadTag

Create or update head tags at any time. Matches existing tags by attribute to avoid duplicates:

updateHeadTag({ name: "description", content: "Some description..." });
updateHeadTag({ tag: "link", rel: "apple-touch-icon", href: "/icon.png" });
updateHeadTag({ property: "og:site_name", content: "Your Brand" });

Set soft: true to skip overwriting existing values. Use innerHTML for structured data and non-self-closing tags. See docs/seo-guide.md for full details.

Programmatic Navigation

window.history.pushState({}, "", "/about/");
window.dispatchEvent(new PopStateEvent("popstate"));

ErrorBoundary

import { ErrorBoundary } from "routerino";

<ErrorBoundary
  fallback={<div>Something went wrong.</div>}
  errorTitleString="Error | My Site"
  debug={window.location.hostname === "localhost"}
>
  <MyComponent />
</ErrorBoundary>;

Static Site Generation (Routerino Forge)

Export the routes and the same app shell that the browser renders, then point Forge at that module:

// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { routerinoForge } from "routerino/forge";

export default defineConfig({
  plugins: [
    react(),
    routerinoForge({
      baseUrl: "https://example.com",
      routes: "./src/App.jsx",
    }),
  ],
});

Requirements:

  • baseUrl is required and must be an HTTP(S) origin such as https://example.com — no path, query, hash, or trailing slash
  • index.html must have <div id="root"></div>
  • The configured module must export routes; exporting its app component as App or the default export preserves the full layout and context during SSG
  • Static route paths must begin with / and cannot contain empty segments, queries, hashes, backslashes, path traversal, or encoded separators
  • Dynamic routes (with :param) are automatically skipped

If the module exports routes but no app component, Forge deliberately renders the matched route element by itself. This route-only mode is useful for simple sites, but it omits any layout or providers that live outside that element. See the full setup for the recommended app structure and hydration entry point.

What you get at build time:

  • Static HTML for every route with full meta tags
  • Dual file generation (/about.html + /about/index.html) for host compatibility; both copies point to the canonical style selected by useTrailingSlash
  • Automatic sitemap.xml and robots.txt
  • 404.html at root for custom error pages
  • Canonical URL and og:url meta tags on every page
  • Root-relative social images resolved against baseUrl; absolute image URLs are preserved
  • A failed route render, 404 render, unsafe route path, invalid configuration, or missing generated file fails the Vite build

Generating Routes from Data

// Build-time data fetching is fully supported
const blogPosts = await fetch("https://api.example.com/posts").then((r) =>
  r.json()
);

export const routes = [
  { path: "/", element: <HomePage />, title: "Home" },
  ...blogPosts.map((post) => ({
    path: `/blog/${post.slug}/`,
    element: <BlogPost post={post} />,
    title: post.title,
    description: post.excerpt,
    imageUrl: post.featuredImage,
  })),
];

Each generated route gets its own static HTML page with proper meta tags and is automatically included in sitemap.xml.

Who Is This For?

Routerino is for React developers building content sites, marketing pages, or JAMstack apps who want full SEO (static HTML, meta tags, sitemaps) without adopting a framework like Next.js or Remix. If you're building a dashboard or an authenticated app, React Router is fine. If you need Google to index your pages, Routerino gives you that at build time with zero new dependencies.

TypeScript

TypeScript definitions are included. Routes are typed as RouteConfig[]:

import type { RouteConfig } from "routerino";

export const routes: RouteConfig[] = [
  { path: "/", element: <HomePage />, title: "Home", description: "Welcome" },
];

Documentation

API Reference

<Routerino> Props

| Prop | Type | Default | Description | | ------------------ | --------------- | ------------------------ | ----------------------------------------------- | | title | string | "" | Site title appended to page titles | | routes | RouteConfig[] | [default] | Array of route configurations | | separator | string | " \| " | Title separator between page and site title | | notFoundTemplate | ReactNode | Built-in 404 | 404 page template | | notFoundTitle | string | "Page not found [404]" | 404 page title | | errorTemplate | ReactNode | Built-in 500 | Error page template | | errorTitle | string | "Page error [500]" | Error page title | | useTrailingSlash | boolean | true | Use trailing slashes in canonical URLs | | usePrerenderTags | boolean | false | Include prerender meta tags for crawlers | | baseUrl | string | null | Base URL for canonical tags (no trailing slash) | | imageUrl | string | null | Default site-wide social image URL | | touchIconUrl | string | null | PWA homescreen icon URL | | debug | boolean | false | Enable console logging | | ignorePatterns | string[] | [] | URL patterns to skip SPA routing |

RouteConfig Object

| Field | Type | Required | Description | | ------------- | -------------- | -------- | --------------------------------------------------- | | path | string | Yes | Route path. Must start with /. Supports :param. | | element | ReactElement | Yes | Rendered JSX element, such as <AboutPage /> | | title | string | No | Page title (site title appended automatically) | | description | string | No | Meta description | | imageUrl | string | No | Social preview image for this route | | tags | HeadTag[] | No | Additional head tags (OG, JSON-LD, etc.) |

HeadTag Object

Common attributes: tag, name, property, content, rel, href, soft, innerHTML. Supports all standard HTML attributes. See updateHeadTag for details.

routerinoForge Options

| Option | Type | Default | Description | | ------------------ | --------- | ------------------------------------------- | ------------------------------------------------ | | baseUrl | string | required | HTTP(S) origin; no path, query, hash, or slash | | routes | string | "./src/routes.jsx" | Path to routes file | | template | string | "index.html" | Built HTML path relative to outputDir | | outputDir | string | "dist" | Build output directory | | generateSitemap | boolean | true | Generate sitemap.xml and robots.txt | | useTrailingSlash | boolean | true | Set to false for /about instead of /about/ | | verbose | boolean | false | Enable detailed build logging | | ssgCacheDir | string | "node_modules/.cache/routerino-forge/ssg" | Parent for isolated temporary SSG bundles |

Contributing

Contributions are welcome. Please create an issue or submit a pull request. Keep it simple!

License

Routerino is MIT licensed.