Routeit
Routeit is a lightweight, type-safe client-side routing library for building modern single-page applications. It provides powerful features like middleware, nested routes, and permission integration with zero dependencies.
What Problem Does Routeit Solve?
Client-side routing is essential for SPAs, but most routers are either too complex, framework-specific, or lack proper TypeScript support. Routeit provides a clean, type-safe routing solution that works with any framework.
Traditional Approach:
// Manual route handling
window.addEventListener('popstate', () => {
const path = window.location.pathname;
if (path === '/') {
renderHome();
} else if (path.startsWith('/users/')) {
const id = path.split('/')[2];
renderUser(id);
} else if (path === '/about') {
renderAbout();
} else {
render404();
}
});
// Manual navigation
function navigate(path) {
history.pushState(null, '', path);
window.dispatchEvent(new PopStateEvent('popstate'));
}With Routeit:
import { createRouter } from '@vielzeug/routeit';
const router = createRouter();
router
.get('/', () => renderHome())
.get('/users/:id', ({ params }) => renderUser(params.id))
.get('/about', () => renderAbout())
.start();
// Navigate with built-in method
router.navigate('/users/123');Comparison with Alternatives
| Feature | Routeit | React Router | Vue Router |
|---|---|---|---|
| Bundle Size | 2.1 KB | ~11KB | ~22KB |
| Dependencies | 0 | React | Vue |
| TypeScript | Native | Good | Good |
| Framework Agnostic | ✅ | ❌ | ❌ |
| Middleware System | ✅ | ❌ | ✅ |
🚀 Key Features
- Type-Safe Parameters – Automatic extraction and type inference
- Middleware System – Powerful async middleware for auth, logging, and more
- Framework Agnostic – Works with React, Vue, Svelte, or vanilla JS
- Nested Routes – Support for child routes and layouts
- Query Parameters – Automatic parsing and array support
- Permission Integration – Works seamlessly with @vielzeug/permit
- Hash & History Mode – Choose between hash-based or HTML5 History API
- Named Routes – Navigate by name with parameter substitution
- Lightweight – Only 2.1 KB gzipped, 0 dependencies
🏁 Quick Start
Install the package:
pnpm add @vielzeug/routeitCreate a basic router:
import { createRouter } from '@vielzeug/routeit';
const router = createRouter();
router
.get('/', () => {
document.getElementById('app').innerHTML = '<h1>Home</h1>';
})
.get('/about', () => {
document.getElementById('app').innerHTML = '<h1>About</h1>';
})
.get('/users/:id', ({ params }) => {
document.getElementById('app').innerHTML = `<h1>User ${params.id}</h1>`;
})
.start();📚 Documentation
- Usage Guide – Comprehensive usage guide
- API Reference – Complete API documentation
- Examples – Real-world examples
💡 Core Concepts
Route Parameters
Extract dynamic segments from URLs:
router.get('/users/:userId/posts/:postId', ({ params }) => {
console.log(params.userId); // '123'
console.log(params.postId); // '456'
});
// Matches: /users/123/posts/456Middleware
Execute code before route handlers:
const requireAuth: Middleware = async (ctx, next) => {
const user = await getCurrentUser();
if (!user) {
ctx.navigate('/login');
return;
}
ctx.user = user;
await next();
};
router.route({
path: '/dashboard',
middleware: requireAuth,
handler: (ctx) => {
console.log('User:', ctx.user);
},
});Query Parameters
Automatic query string parsing:
router.get('/search', ({ query }) => {
console.log(query.q); // 'test'
console.log(query.filter); // ['new', 'sale']
});
// Matches: /search?q=test&filter=new&filter=saleNamed Routes
Navigate by route name:
router.route({
path: '/users/:id',
name: 'userDetail',
handler: ({ params }) => {
console.log('User:', params.id);
},
});
// Navigate using name
router.navigateTo('userDetail', { id: '123' });
// Or build URL
const url = router.urlFor('userDetail', { id: '123' }); // '/users/123'❓ FAQ
Q: Can I use this with React/Vue/Svelte?
A: Yes! Routeit is framework-agnostic. See the Examples for integration examples.
Q: How do I handle authentication?
A: Use middleware! Check the Usage Guide for auth examples.
Q: Does it support nested routes?
A: Yes, through the children property. See Nested Routes.
Q: What about lazy loading?
A: Use async middleware to load route modules dynamically. See Examples.
Q: Can I integrate with @vielzeug/permit?
A: Absolutely! See the Permission Integration section.
🐛 Troubleshooting
Routes not matching:
- Check path syntax – use
:paramfor parameters - Ensure router is started with
.start() - Verify base path configuration
Middleware not executing:
- Make sure to call
await next()to continue the chain - Check execution order (global → route → handler)
404 not working:
- Provide a
notFoundhandler in router options - Check if another route is matching first
Hash mode not working:
- Ensure
mode: 'hash'is set in router options - Check URL format includes
#(e.g.,#/about)
🤝 Contributing
Contributions are welcome! Please read our Contributing Guidelines.
📄 License
MIT © Vielzeug