the problem
Vue Router’s beforeEach global guards are flexible but unstructured: every project ends up
re-inventing role checks, redirect chains, and “is the user logged in” branching. That logic
gets glued to components or composables, becomes hard to test in isolation, and falls apart
once an app needs nested route protection (admin → org → resource).
the approach
Citadel splits the problem into two primitives:
- Outposts — composable middleware functions, each one returning a verdict (
allow,deny,redirect,next). - Verdict pipeline — outposts run in order, short-circuiting on the first non-
nextverdict. The result is a predictable, traceable navigation decision.
Type-safe end-to-end: outpost factories carry their context types through the pipeline so the final guard signature reflects the protected route’s actual data needs.
stack
- TypeScript 5 (strict)
- Vue Router 4 + 5 (peer dependency, dual-version support)
- Vitest for unit coverage
- Vite + tsup for the library build
links
- Homepage / docs: https://kassaila.github.io/vue-router-citadel/
- npm:
vue-router-citadel - Repo: https://github.com/Kassaila/vue-router-citadel