Skip to content

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

GuardsMiddleware
Registrationrouter.beforeEach()router.use()
Can redirectYes (throw redirect())Yes (throw redirect())
Can blockNoYes (return without next())
RunsBefore middlewareAfter guards
Use caseAuth checks, redirectsLogging, analytics, validation

Important Notes

TIP

Guards run before middleware. Both run before loaders. This ensures auth checks happen before data fetching.

Next Steps

Released under the MIT License.