@power-seo/redirects
v1.0.12
Published
Redirect rule engine with URL pattern matching and framework adapters (Next.js, Remix, Express)
Maintainers
Readme
@power-seo/redirects
Define redirect rules once — apply them in Next.js, Remix, and Express with typed exact, glob, and regex URL matching.
@power-seo/redirects is a framework-agnostic URL redirect rule engine for TypeScript — define RedirectRule[] once in a shared config file and generate Next.js next.config.js redirect arrays, Remix loader functions, and Express middleware from the same typed source of truth. Evaluate rules with exact string matching, glob wildcards with :param segments, or full regular expressions. First-match-wins priority ordering, configurable trailing-slash handling, and named parameter substitution are included. All adapters are tree-shakeable — import only the framework you target.
Zero runtime dependencies — pure TypeScript, no native bindings, edge-compatible.
Why @power-seo/redirects?
| | Without | With |
| --------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------- |
| Cross-framework rules | ❌ Duplicated in next.config.js, Remix loaders, Express middleware | ✅ One RedirectRule[] — all three from a single file |
| Pattern matching | ❌ Ad-hoc regex scattered across route files | ✅ Exact, glob, and regex with typed API |
| Named params | ❌ Manual capture group indexing | ✅ :param substitution in destination URLs |
| Trailing slash | ❌ Inconsistent per route | ✅ Configurable 'strip' / 'add' / 'ignore' |
| TypeScript | ❌ statusCode typos detected at runtime | ✅ RedirectStatusCode union enforces 301 \| 302 at compile time |
| Testing | ❌ Deploy to verify redirects work | ✅ engine.match() in unit tests — zero-cost synchronous check |
| SEO | ❌ Missing 301s break link equity during migrations | ✅ Typed rules prevent status code mistakes |
Features
- Exact matching — byte-for-byte URL comparison with optional case sensitivity control
- Glob pattern matching —
*wildcard and:paramnamed segment support (e.g./blog/:slug) - Regex pattern matching — full regular expression matching with capture group extraction
- 301 and 302 status codes — permanent and temporary redirect support via
RedirectStatusCodeunion type :paramsubstitution —substituteParams()for named parameter placeholders in destination URLs- Trailing slash normalization — configurable
'strip','add', or'ignore'per engine - Case-sensitive option — per-engine case sensitivity control
- Next.js adapter —
toNextRedirects(rules)mapsstatusCode: 301→permanent: trueautomatically - Remix loader adapter —
createRemixRedirectHandler(rules)returns a Remix-compatible loader function - Express middleware adapter —
createExpressRedirectMiddleware(rules)returns an ExpressRequestHandler - Priority-ordered evaluation — rules are evaluated top-to-bottom; first match wins
- Zero runtime dependencies — no external libraries; edge-compatible
- Full TypeScript types — typed
RedirectRule,RedirectMatch,RedirectEngine,RedirectEngineConfig - Tree-shakeable — import only the adapters you use;
"sideEffects": false
Comparison
| Feature | @power-seo/redirects | next/redirects (config) | vercel.json | nginx rewrite |
| ---------------------------------- | :------------------: | :---------------------: | :---------: | :-----------: |
| Works in Next.js | ✅ | ✅ | ✅ | ❌ |
| Works in Remix | ✅ | ❌ | ❌ | ❌ |
| Works in Express | ✅ | ❌ | ❌ | ✅ |
| Typed TypeScript API | ✅ | ❌ | ❌ | ❌ |
| Named :param substitution | ✅ | ✅ | ✅ | ✅ |
| Regex pattern support | ✅ | ✅ | ✅ | ✅ |
| Glob wildcard support | ✅ | ✅ | ✅ | ✅ |
| Programmatic rule testing | ✅ | ❌ | ❌ | ❌ |
| One rule set → multiple frameworks | ✅ | ❌ | ❌ | ❌ |
| Zero runtime dependencies | ✅ | ✅ | ✅ | ✅ |
| Tree-shakeable | ✅ | ❌ | ❌ | ❌ |
Installation
npm install @power-seo/redirectsyarn add @power-seo/redirectspnpm add @power-seo/redirectsQuick Start
import { createRedirectEngine } from '@power-seo/redirects';
const engine = createRedirectEngine({
rules: [
{ source: '/old-about', destination: '/about', statusCode: 301 },
{ source: '/blog/:slug', destination: '/articles/:slug', statusCode: 301 },
{ source: '/docs/*', destination: '/documentation/*', statusCode: 302 },
],
});
const match = engine.match('/blog/my-seo-guide');
// { rule: {...}, resolvedDestination: '/articles/my-seo-guide', statusCode: 301 }
const noMatch = engine.match('/no-redirect-here');
// nullUsage
Shared Rule File
Define rules once and import them into every framework adapter:
// redirects.config.ts
import type { RedirectRule } from '@power-seo/redirects';
export const rules: RedirectRule[] = [
{ source: '/old-about', destination: '/about', statusCode: 301 },
{ source: '/blog/:slug', destination: '/articles/:slug', statusCode: 301 },
{ source: '/docs/*', destination: '/documentation/*', statusCode: 302 },
{ source: '/products/:id(\\d+)', destination: '/items/:id', statusCode: 301 },
];Next.js — next.config.js
toNextRedirects() converts RedirectRule[] to the format Next.js expects. statusCode: 301 maps to permanent: true.
// next.config.js
const { toNextRedirects } = require('@power-seo/redirects');
const { rules } = require('./redirects.config');
module.exports = {
async redirects() {
return toNextRedirects(rules);
},
};Remix — Catch-All Route
createRemixRedirectHandler() returns a Remix loader function for use in a $.tsx catch-all route.
// app/routes/$.tsx
import { createRemixRedirectHandler } from '@power-seo/redirects';
import { rules } from '~/redirects.config';
export const loader = createRemixRedirectHandler(rules);Express — Middleware
createExpressRedirectMiddleware() returns an Express RequestHandler. Register it early in the middleware chain.
import express from 'express';
import { createExpressRedirectMiddleware } from '@power-seo/redirects';
import { rules } from './redirects.config';
const app = express();
app.use(createExpressRedirectMiddleware(rules));Trailing Slash and Case Sensitivity
const engine = createRedirectEngine(rules, {
caseSensitive: false, // match /About and /about equally
trailingSlash: 'remove', // /about/ → /about before matching
});Parameter Substitution
import { substituteParams } from '@power-seo/redirects';
substituteParams('/articles/:slug', { slug: 'react-seo-tips' });
// '/articles/react-seo-tips'Testing Rules in CI
import { createRedirectEngine } from '@power-seo/redirects';
import { rules } from './redirects.config';
const engine = createRedirectEngine(rules);
const match1 = engine.match('/old-about');
expect(match1?.resolvedDestination).toBe('/about');
expect(match1?.statusCode).toBe(301);
const match2 = engine.match('/blog/my-post');
expect(match2?.resolvedDestination).toBe('/articles/my-post');
expect(match2?.statusCode).toBe(301);
expect(engine.match('/no-match')).toBeNull();API Reference
createRedirectEngine(initialRules, config)
function createRedirectEngine(
initialRules?: RedirectRule[],
config?: RedirectEngineConfig,
): RedirectEngine;| Parameter | Type | Default | Description |
| ---------------------- | ----------------------------- | ---------- | --------------------------------------- |
| initialRules | RedirectRule[] | [] | Initial ordered array of redirect rules |
| config.caseSensitive | boolean | false | Case-sensitive URL matching |
| config.trailingSlash | 'keep' \| 'remove' \| 'add' | 'remove' | Trailing slash normalization |
Returns RedirectEngine: { match(url: string): RedirectMatch | null; addRule(rule: RedirectRule): void; removeRule(source: string): boolean; getRules(): RedirectRule[] }.
matchExact(url, source, config?)
function matchExact(url: string, source: string, config?: RedirectEngineConfig): boolean;Returns boolean. Byte-for-byte URL comparison after normalization.
matchGlob(url, pattern, config?)
function matchGlob(
url: string,
pattern: string,
config?: RedirectEngineConfig,
): { matched: boolean; params: Record<string, string> };Returns { matched: boolean; params: Record<string, string> }. Supports :param named segments and * wildcard matching.
matchRegex(url, pattern, destination, config?)
function matchRegex(
url: string,
pattern: string,
destination: string,
config?: RedirectEngineConfig,
): { matched: boolean; destination: string };Returns { matched: boolean; destination: string }. Full regular expression matching with capture group substitution into the destination.
substituteParams(template, params)
substituteParams('/articles/:slug', { slug: 'react-seo-tips' });
// '/articles/react-seo-tips'toNextRedirects(rules)
Converts RedirectRule[] to Next.js redirects() array format. Maps statusCode: 301 → permanent: true, statusCode: 302 → permanent: false.
createRemixRedirectHandler(rules)
Returns a Remix LoaderFunction that issues redirect() when a rule matches, or returns null otherwise.
createExpressRedirectMiddleware(rules)
Returns an Express RequestHandler that calls res.redirect() on match or next() when no rule matches.
Types
| Type | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| RedirectStatusCode | 301 \| 302 \| 308 \| 307 \| 410 (from @power-seo/core) |
| RedirectRule | { source: string; destination: string; statusCode: RedirectStatusCode; isRegex?: boolean } (from @power-seo/core) |
| RedirectMatch | { rule: RedirectRule; resolvedDestination: string; statusCode: RedirectStatusCode } |
| RedirectEngineConfig | { caseSensitive?: boolean; trailingSlash?: 'keep' \| 'remove' \| 'add' } |
| RedirectEngine | { match(url: string): RedirectMatch \| null; addRule(rule: RedirectRule): void; removeRule(source: string): boolean; getRules(): RedirectRule[] } |
| NextRedirect | { source: string; destination: string; permanent: boolean } |
Use Cases
- Site migrations — redirect hundreds of old URLs to new paths with a typed rule array
- URL restructuring for SEO — enforce new URL patterns with 301 redirects to preserve link equity
- Trailing slash normalization — enforce consistent URL format across all routes
- Locale redirects — redirect
/en/aboutto/aboutwith glob patterns - Legacy URL handling — redirect old numeric IDs to slug-based URLs with regex patterns
- Canonical URL enforcement — redirect
http:tohttps:,www.to non-www - Multi-framework monorepos — define rules once, generate Next.js, Remix, and Express configs from the same file
Architecture Overview
- Pure TypeScript — no compiled binary, no native modules
- Zero runtime dependencies — no external libraries; safe on any runtime
- Framework-agnostic core —
createRedirectEngine()has no framework imports; adapters are separate named exports - First-match-wins — rules are evaluated top-to-bottom; order matters for overlapping patterns
- SSR compatible —
toNextRedirects()runs at build time; Remix and Express adapters run at request time - Edge runtime safe — no Node.js-specific APIs; runs in Cloudflare Workers, Vercel Edge, Deno
- Tree-shakeable —
"sideEffects": false; import only the adapters you use - Dual ESM + CJS — ships both formats via tsup for any bundler or
require()usage
Supply Chain Security
- No install scripts (
postinstall,preinstall) - No runtime network access
- No
evalor dynamic code execution - CI-signed builds — all releases published via verified
github.com/CyberCraftBD/power-seoworkflow - Safe for SSR, Edge, and server environments
The @power-seo Ecosystem
All 17 packages are independently installable — use only what you need.
| Package | Install | Description |
| ------------------------------------------------------------------------------------------ | ----------------------------------- | ----------------------------------------------------------------------- |
| @power-seo/core | npm i @power-seo/core | Framework-agnostic utilities, types, validators, and constants |
| @power-seo/react | npm i @power-seo/react | React SEO components — meta, Open Graph, Twitter Card, breadcrumbs |
| @power-seo/meta | npm i @power-seo/meta | SSR meta helpers for Next.js App Router, Remix v2, and generic SSR |
| @power-seo/schema | npm i @power-seo/schema | Type-safe JSON-LD structured data — 23 builders + 22 React components |
| @power-seo/content-analysis | npm i @power-seo/content-analysis | Yoast-style SEO content scoring engine with React components |
| @power-seo/readability | npm i @power-seo/readability | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI |
| @power-seo/preview | npm i @power-seo/preview | SERP, Open Graph, and Twitter/X Card preview generators |
| @power-seo/sitemap | npm i @power-seo/sitemap | XML sitemap generation, streaming, index splitting, and validation |
| @power-seo/redirects | npm i @power-seo/redirects | Redirect engine with Next.js, Remix, and Express adapters |
| @power-seo/links | npm i @power-seo/links | Link graph analysis — orphan detection, suggestions, equity scoring |
| @power-seo/audit | npm i @power-seo/audit | Full SEO audit engine — meta, content, structure, performance rules |
| @power-seo/images | npm i @power-seo/images | Image SEO — alt text, lazy loading, format analysis, image sitemaps |
| @power-seo/ai | npm i @power-seo/ai | LLM-agnostic AI prompt templates and parsers for SEO tasks |
| @power-seo/analytics | npm i @power-seo/analytics | Merge GSC + audit data, trend analysis, ranking insights, dashboard |
| @power-seo/search-console | npm i @power-seo/search-console | Google Search Console API — OAuth2, service account, URL inspection |
| @power-seo/integrations | npm i @power-seo/integrations | Semrush and Ahrefs API clients with rate limiting and pagination |
| @power-seo/tracking | npm i @power-seo/tracking | GA4, Clarity, PostHog, Plausible, Fathom — scripts + consent management |
About CyberCraft Bangladesh
CyberCraft Bangladesh is a Bangladesh-based enterprise-grade software development and Full Stack SEO service provider company specializing in ERP system development, AI-powered SaaS and business applications, full-stack SEO services, custom website development, and scalable eCommerce platforms. We design and develop intelligent, automation-driven SaaS and enterprise solutions that help startups, SMEs, NGOs, educational institutes, and large organizations streamline operations, enhance digital visibility, and accelerate growth through modern cloud-native technologies.
© 2026 CyberCraft Bangladesh · Released under the MIT License
