For a while now, I've found myself in one of those situations where a simple problem turns into a "might as well build something"
moment.
On my main server, this is easy—because I run a buildscript during deployment that adds all the redirects from a json file to .htaccess
and call it a day.
But here's the thing: I also use services like Render.com and Appwrite Sites for PR previews. And guess what? Those redirects don't work there because the SSGs don't have that capability and the platform don't always support these.
So I had a choice: manually create redirect HTML files just for these platforms, or spend some time to build a proper solution. I obviously chose the latter 😄
The real problem
Static sites are great until you need to handle redirects. Most providers—especially the free ones—either don't support server-side redirects or make them unnecessarily complicated. And when you're using multiple hosting services for different purposes (like I do with preview environments), maintaining redirects can be a hassle.
I looked around for existing solutions but the one I found was managing the redirects via enhanceApp
hook. If you don't know, redirections from that hook can briefly show a 404
. Ehhh, big NO for me.
VitePress
despite being fantastic, didn't have a clean way to handle this.
Enter Routex
What I wanted was simple: define redirects in my VitePress config and have everything else handled automatically. No manual HTML files, no server configuration, no headaches.
That's exactly what Routex
does:
// .vitepress/config.ts
import { routex } from 'routex';
export default defineConfig({
/* other existing config */
vite: {
plugins: [
routex({
'/cls': '/blog/chrome-shortcuts',
'/appexpress': '/blog/appexpress',
'/ghosler': '/blog/ghosler'
})
]
}
});
And that's it. The plugin handles the rest, generates redirect pages during build, injects client-side navigation scripts, and even adds fallbacks for when JavaScript is disabled.
How it actually works
The plugin does three things:
- Client-side interception: When someone navigates to an old URL, JavaScript catches it and redirects instantly
- Static page generation: Creates actual HTML files for each redirect during build time
- Fallback support: Uses meta refresh tags so redirects work even without JavaScript
Note: When running pnpm dev
, the plugin manages redirects on the fly, so changes are reflected immediately as you develop.
This means it works everywhere: GitHub Pages, Netlify, Vercel, my PHP server, Render previews, Appwrite hosting, you name it.
The validation bit
One thing I added was the redirect validation. It checks for:
- Dead links
- Self-references (A → A)
- Circular redirects (A → B → A)
- Conflicts with existing pages to not override them
Saves you from deploying broken redirects and then wondering why your site is acting weird.
Advanced options
For more complex scenarios, you can customize the behavior:
routex({
rules: {
'/cls': '/blog/chrome-shortcuts',
'/appexpress': '/blog/appexpress',
'/ghosler': '/blog/ghosler',
},
options: {
redirectDelay: 2, // Delay in seconds (default: 0)
addCanonical: true, // Add canonical link tags (default: false)
addNoIndexMeta: true, // Add noindex meta tag (default: false)
template: './template.html', // Custom template path or raw string
overrideExisting: false, // Allow overriding existing pages (default: false)
ignoreDeadLinks: false // Skip validation for missing destinations (default: false)
}
});
Real usage
I've started using this on my own site for PR previews, and it's been working great. The plugin generates clean redirect pages that blend with your site's design, and the validation catches issues before they hit production.
It's particularly useful when migrating from other platforms or when you need to consolidate or test content without breaking existing links.
So that's Routex, born from not wanting to manually do stuff with files. It's available as @itznotabug/routex
on npm, and the code is up on https://github.com/ItzNotABug/routex.
If you're dealing with VitePress redirects and don't want to mess with server configs or manual HTML files, give it a shot. It might save you some time!