Guards & Middleware
Route Middleware
Middleware runs on every navigation. It can continue, redirect, or block:
ts
router.use(async (to, from, next) => {
analytics.page(to.fullPath);
return next();
});Route Guards
Guards are observational — they can redirect but cannot block silently:
ts
router.beforeEach((to, from, context) => {
if (to.meta.requiresAuth && !context.mesh.getState().auth.token) {
throw redirect("/login", { search: { returnTo: to.fullPath } });
}
});redirect
ts
import { redirect } from "statemesh-core/router";
// In a guard
throw redirect("/login");
// With search params
throw redirect("/login", { search: { returnTo: "/checkout" } });
// With replace
throw redirect("/dashboard", { replace: true });Guard vs Middleware
| Guards | Middleware | |
|---|---|---|
| Registration | router.beforeEach() | router.use() |
| Can redirect | Yes (throw redirect()) | Yes (throw redirect()) |
| Can block | No | Yes (return without next()) |
| Runs | Before middleware | After guards |
| Use case | Auth checks, redirects | Logging, analytics, validation |
Important Notes
TIP
Guards run before middleware. Both run before loaders. This ensures auth checks happen before data fetching.
Next Steps
- Data Loading — Loaders and error recovery
- Advanced — Keep-alive, prefetch, shared elements
