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

route-manager-plugin

v1.0.12

Published

Plugin for managing routes and redirects.

Readme

Route Manager Plugin

A Strapi 5 plugin for managing URL routes, redirects, sitemaps, and public preview links in a multi-tenant environment. Automatically syncs routes when content entries are created, updated, or deleted.

Features

  • Navigation Menu Builder — Visual tree editor for creating and managing navigation menus with drag-and-drop reordering and re-parenting
  • Automatic Route Sync — Routes are auto-created/updated/deleted when content entries with a uid (slug) field change
  • Collection Base Paths — Configure a base path per collection (e.g., /blog for blog entries → /blog/my-post)
  • Redirect Management — Automatic 301 redirects on slug changes, with loop detection and prevention
  • Public Preview — Shareable preview URLs with rotating cryptographic tokens (24h expiry)
  • Sitemap Generation — XML sitemap with per-route priority, changefreq, and include/exclude controls
  • Multi-Domain Support — Full integration with @sensinum/strapi-plugin-multi-domain for domain-scoped routes
  • Path Details Panel — Content Manager side panel showing path, full URL, and preview URL with copy buttons
  • URL Picker Custom Field — Custom field type for selecting internal routes in content entries

Installation

The plugin lives in src/plugins/route-manager-plugin and is configured in config/plugins.ts:

// config/plugins.ts
export default () => ({
  'route-manager-plugin': {
    enabled: true,
    resolve: './src/plugins/route-manager-plugin',
  },
});

Build the plugin:

cd src/plugins/route-manager-plugin
npx strapi-plugin build

Configuration

Plugin Config Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | baseUrl | string | http://localhost:1337 | Base URL for full URL display and sitemap generation | | siteName | string | '' | Site name displayed in admin UI | | frontendBaseUrl | string | http://localhost:3000 | Frontend URL used for preview link construction | | previewTokenCronInterval | string | 0 * * * * | Cron schedule for preview token rotation |

Environment Variables

# Used by the plugin's default config
FRONTEND_BASE_URL=https://yourdomain.com

# Used by the webhook system (in the Strapi app, not the plugin)
BFF_WEBHOOK_URL=http://localhost:8080/webhook/strapi-tenant
BFF_WEBHOOK_SECRET=your-webhook-secret

Multi-Domain Integration

When used with the multi-domain plugin, baseUrl is resolved per-domain via an extension service override in the app's src/index.ts. The plugin does not need explicit baseUrl config — it's derived from the domain's customFields.url.

Architecture

Two Auth Systems

The plugin exposes routes on two separate APIs:

| API | URL Pattern | Auth | Consumer | |-----|-------------|------|----------| | Admin API | /route-manager-plugin/... | Admin JWT | Strapi admin panel | | Content API | /api/route-manager-plugin/... | API Token | BFF / external services |

Admin JWT tokens cannot access content API routes and vice versa. The admin panel uses getFetchClient from @strapi/admin/strapi-admin which handles admin auth automatically.

Content Types

Navigation Menu (plugin::route-manager-plugin.navigation-menu)

| Field | Type | Description | |-------|------|-------------| | title | string | Menu display name | | maxDepth | integer (1–5) | Maximum allowed nesting depth | | placement | enum | standard, global_nav, or global_footer | | logo | media (single) | Optional logo image | | items | JSON | Nested tree of navigation items (structured JSON) |

Route (plugin::route-manager-plugin.route)

| Field | Type | Description | |-------|------|-------------| | path | string (required) | URL path (e.g., /blog/my-post) | | contentType | string (required) | Strapi UID (e.g., api::page.page) or virtual | | contentId | integer (required) | Entry ID (0 for virtual routes) | | entryTitle | string | Display title for the route | | isActive | boolean | Whether the route is live | | isParentRoute | boolean | Whether this is a collection base route | | applyToAllEntries | boolean | Collection-level base path marker | | sitemapInclude | boolean | Include in sitemap generation | | sitemapPriority | decimal | Sitemap priority (0.0–1.0) | | sitemapChangefreq | string | Sitemap change frequency |

Redirect (plugin::route-manager-plugin.redirect)

| Field | Type | Description | |-------|------|-------------| | source | string | Source path (from) | | destination | string | Destination path (to) | | statusCode | integer | HTTP status code (301, 302) | | isActive | boolean | Whether redirect is active |

Preview Token (plugin::route-manager-plugin.preview-token)

| Field | Type | Description | |-------|------|-------------| | token | string (unique) | 64-char base64url cryptographic token | | expiresAt | datetime | Expiration timestamp |

API Reference

Content API (requires API token)

| Method | Path | Description | |--------|------|-------------| | GET | /api/route-manager-plugin/navigation-menus | All navigation menus (domain-scoped) | | GET | /api/route-manager-plugin/navigation-menus/:documentId | Single menu with resolved images | | GET | /api/route-manager-plugin/routes | All routes (domain-scoped) | | GET | /api/route-manager-plugin/routes/root | Root-level routes only | | GET | /api/route-manager-plugin/routes/children/:parentPath | Child routes of a path | | GET | /api/route-manager-plugin/routes/tree | Full route tree structure | | GET | /api/route-manager-plugin/routes/breadcrumbs/:path | Breadcrumb trail for a path | | GET | /api/route-manager-plugin/routes/search | Search/paginate routes | | GET | /api/route-manager-plugin/redirects | All redirects (domain-scoped) | | GET | /api/route-manager-plugin/sitemap.xml | Generated XML sitemap |

Content API (public, no auth)

| Method | Path | Description | |--------|------|-------------| | GET | /api/route-manager-plugin/config | Plugin config (baseUrl, siteName) | | GET | /api/route-manager-plugin/preview/token | Current valid preview token | | GET | /api/route-manager-plugin/preview/validate?token=... | Validate a preview token | | GET | /api/route-manager-plugin/preview/url?path=... | Full preview URL for a path |

Admin API (requires admin JWT)

Full CRUD for routes, redirects, collections, sitemap settings, and all utility endpoints (validate-path, generate-slug, bulk operations). See server/src/routes/admin/index.ts for the complete list.

Automatic Behaviors

Route Lifecycle

When a content entry with a uid-type field is:

  • Created → A route is auto-created at /{collection-base-path}/{slug} or /{slug} if no base path
  • Updated (slug change) → Route path is updated + a 301 redirect is created from old → new path
  • Deleted → The route is removed

Redirect Loop Prevention

When a slug is changed back to a previous value (A → B → A), the plugin:

  1. Removes any existing redirect FROM the new destination (would cause a loop)
  2. Removes any existing redirect TO the old path (stale chain)
  3. Creates the new redirect

Slug Validation

A Koa middleware validates slugs on create/update/publish to prevent duplicate route paths. Returns a 400 error with a user-visible message if a conflict is detected.

Preview Token Rotation

A cron job (configurable via previewTokenCronInterval) generates new tokens and cleans up expired ones. Default: every hour.

Admin Panel Features

Path Details Panel

Injected into the Content Manager edit view via addEditViewSidePanel. Shows:

  • Path — The route path with copy button
  • Full URL — Domain + path with copy button
  • Public Preview — Shareable preview URL (token auto-fetched from server)
  • Edit Path — Link to the route manager plugin page

Plugin Page (Tabs)

  • Menus — Create and manage navigation menus with a visual tree builder. Drag-and-drop reordering and re-parenting with depth enforcement.
  • Routes — Search, filter, create, edit, delete routes. Bulk operations supported.
  • Redirects — Manage redirect rules with source/destination/status code.
  • Sitemap — Configure per-route sitemap settings (include, priority, changefreq). Preview/download XML.

Navigation Menu Builder

The Menus tab provides a full navigation management UI:

  • Menu Settings — Title, max nesting depth (1–5), placement (Standard / Global Navigation / Global Footer), and optional logo upload
  • Visual Tree Editor — Card-based tree with connector lines, inspired by strapi-plugin-navigation (VirtusLab)
  • Side Panel Editing — Click the edit icon on any nav item to open the editing form in a right-side panel (label, URL, type, image)
  • Drag-and-Drop — Reorder items within siblings or re-parent by dragging horizontally. Depth limits enforced.
  • CTA Support — Click a nav item label to mark it as CTA (blue badge). Only one CTA per menu. Click the badge to remove.
  • Media Picker — Upload images for nav items and logo directly to a dedicated "Navigation Menus" folder in the Media Library
  • Placement Uniqueness — Only one menu per domain can be set as Global Navigation or Global Footer
  • Multi-Domain Aware — Menus are scoped to the active domain via manual domain link insertion
  • Bulk Delete — Checkbox selection with bulk delete for cleanup

URL Picker Custom Field

Register in your content types to let editors pick internal routes from a dropdown:

{
  "type": "customField",
  "customField": "plugin::route-manager-plugin.url-picker"
}

Webhook Integration

The plugin fires database lifecycle hooks that the Strapi app's src/webhooks/bff-cache-invalidation.ts listens to. On route/redirect/page changes, a webhook is sent to the BFF for cache invalidation.

Tracked models: page, route, redirect

Webhook payload:

{
  "event": "entry.create|entry.update|entry.delete",
  "model": "page",
  "tenantCode": "primax",
  "entry": { "id": 14, "documentId": "abc123" }
}

Development

# Build the plugin
cd src/plugins/route-manager-plugin
npx strapi-plugin build

# Watch for changes during development
npx strapi-plugin watch

# Type-check
npm run test:ts:front
npm run test:ts:back

File Structure

route-manager-plugin/
├── admin/src/
│   ├── components/          # UI components (NavigationTab, NavigationEditor, RoutesTab, etc.)
│   ├── hooks/               # usePluginConfig, useRoutes
│   ├── pages/               # HomePage (plugin main page)
│   └── utils/
│       ├── api.ts           # Authenticated fetch helpers (getFetchClient)
│       ├── navTreeUtils.ts  # Navigation tree manipulation (add, remove, move, reorder)
│       ├── flattenTree.ts   # Tree flattening and DnD projection utilities
│       └── routeUtils.ts    # Slug generation, validation, bulk ops
├── docs/
│   └── NAVIGATION-MENUS-API.md  # BFF integration guide for navigation menus
├── server/src/
│   ├── bootstrap.ts         # Lifecycle hooks registration, slug validation middleware
│   ├── config/index.ts      # Default config and validation
│   ├── content-types/       # Route, Redirect, PreviewToken, NavigationMenu schemas
│   ├── controllers/         # Main controller + preview + navigation-menu controllers
│   ├── middlewares/          # Route lifecycle (auto-create/update/delete routes)
│   ├── routes/
│   │   ├── admin/           # Admin API routes (JWT auth)
│   │   └── content-api/     # Content API routes (token auth)
│   └── services/            # Preview service, navigation-menu service
└── package.json