STX Router
raw JSON →STX Router is a file-based routing solution specifically designed for the Stacks.js full-stack framework. It facilitates automatic discovery of `.stx` templates, enables nested layouts, offers typed route parameters for enhanced developer experience and compile-time safety, supports middleware for request processing, and provides robust client-side SPA navigation. As of version 0.2.12, the package is in active pre-1.0 development, integrating seamlessly into the Stacks.js ecosystem which leverages TypeScript and Bun for performance and type-safety. The project generally follows a convention-over-configuration philosophy, aiming for rapid application development. Its current release cadence is frequent, indicating ongoing feature development and potential for breaking changes between minor versions as it approaches a stable 1.0 release.
Common errors
error Error: Route not found for path '/your/path' ↓
.stx file exists for the requested path (e.g., views/your/path.stx or views/your/[param].stx). Check the routes configuration in createRouter to ensure it points to the correct base directory. Also, confirm no typos in the URL or route definition. error TypeError: Cannot read properties of undefined (reading 'params') ↓
/users/:id). Before accessing params, consider optional chaining (req.params?.id) or a null/undefined check to handle cases where parameters might not exist gracefully. error SyntaxError: Named export 'defineMiddleware' not found in module '@stacksjs/router' ↓
import { defineMiddleware } from '@stacksjs/router' for named exports. If the module primarily offers a default export, you would use import Router from '@stacksjs/router' (though stx-router uses named exports). Also, verify your project's tsconfig.json and package.json ("type": "module") are correctly configured for ESM. Warnings
breaking As a pre-1.0 release, `stx-router` may introduce breaking changes in minor versions (e.g., 0.2.x to 0.3.x). APIs, configuration options, and internal behaviors are subject to change without strict adherence to semantic versioning until a stable 1.0 release. ↓
gotcha File-based routing relies on specific directory structures and naming conventions for `.stx` templates. Deviating from these conventions will result in routes not being discovered or matched correctly, leading to 404 errors. ↓
gotcha Middleware execution order and application scope can be a common source of bugs. Middleware might not execute for certain routes, or the order of execution might be unexpected, especially with overlapping paths. ↓
gotcha Typed route parameters, while beneficial, require careful definition in your route files (or inferred types). Incorrectly accessing or assuming the type of a route parameter (e.g., treating a string ID as a number without parsing) can lead to runtime `TypeError`s. ↓
Install
npm install stx-router yarn add stx-router pnpm add stx-router Imports
- createRouter wrong
const { createRouter } = require('@stacksjs/router')correctimport { createRouter } from '@stacksjs/router' - defineMiddleware wrong
import defineMiddleware from '@stacksjs/router'correctimport { defineMiddleware } from '@stacksjs/router' - RouteContext
import type { RouteContext } from '@stacksjs/router'
Quickstart
import { createRouter, defineMiddleware } from '@stacksjs/router';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Define a simple authentication middleware
const authMiddleware = defineMiddleware((req, res, next) => {
const isAuthenticated = req.headers.get('authorization') === 'Bearer my-secret-token';
if (isAuthenticated) {
console.log('User is authenticated');
next();
} else {
console.warn('Authentication failed: Missing or invalid token');
res.status(401).send('Unauthorized');
}
});
// Imagine your .stx templates are in a 'views' directory
// For a file-based router, you'd typically have files like:
// views/index.stx, views/users/[id].stx, views/admin/dashboard.stx
const router = createRouter({
routes: join(__dirname, 'views'), // Points to your .stx template directory
middleware: {
'/admin/*': [authMiddleware], // Apply authMiddleware to all /admin routes
},
// You might define custom error handlers or other router options here
onNotFound: (req, res) => {
res.status(404).send('Custom 404 Not Found Page');
},
});
// Example: How to manually handle a request (in a server context, e.g., Bun.serve)
// In a real Stacks.js app, this would be abstracted away by the framework's server.
async function handleRequest(request: Request) {
const url = new URL(request.url);
console.log(`Incoming request: ${request.method} ${url.pathname}`);
// Simulate router matching and processing
// In a full Stacks.js app, this would trigger .stx template rendering
const response = await router.handle(request);
// For demonstration, a simple placeholder response if router doesn't explicitly respond
if (!response.headers.has('X-Router-Handled')) {
if (url.pathname === '/') {
return new Response('Welcome to the STX App!', { status: 200 });
} else if (url.pathname.startsWith('/users/')) {
const userId = url.pathname.split('/').pop();
return new Response(`User profile for ID: ${userId}`, { status: 200 });
}
return new Response('Default response for unmatched routes or handled by custom 404', { status: 404 });
}
return response;
}
// This part would typically be part of your Stacks.js server setup
// Bun.serve({
// fetch: handleRequest,
// port: 3000,
// });
// console.log('STX Router example server running on http://localhost:3000');
// To test manually:
// await handleRequest(new Request('http://localhost:3000/'));
// await handleRequest(new Request('http://localhost:3000/users/123'));
// await handleRequest(new Request('http://localhost:3000/admin/dashboard', { headers: { 'Authorization': 'Bearer my-secret-token' } }));
// await handleRequest(new Request('http://localhost:3000/admin/settings')); // Should be unauthorized
// await handleRequest(new Request('http://localhost:3000/nonexistent')); // Should trigger custom 404