Skip to content

🪝 Navigation Hooks

Citadel integrates with Vue Router's navigation lifecycle through three hooks. Each hook triggers the patrol system that processes all registered outposts.

📋 Hook Types

HookWhenCan BlockUse Case
BEFORE_EACHBefore navigation startsYesAuth, permissions, redirects
BEFORE_RESOLVEAfter async components resolvedYesData validation, final checks
AFTER_EACHAfter navigation completedNoAnalytics, logging, side effects

For best understanding, read Vue Router's

Navigation Guards and The Full Navigation Resolution Flow.

🔄 Where Hooks Fit

Each hook triggers patrol which processes all applicable outposts in priority order.

📊 What Happens Inside a Hook

What happens when a navigation hook is triggered:

INFO

Logging and debug breakpoints only trigger when there are outposts to process for the current hook. If no outposts are registered for a hook, it returns ALLOW silently.

⚙️ Specifying Hooks

By default, outposts use beforeEach. Override with the hooks option:

typescript
import { NavigationHooks } from 'vue-router-citadel';

citadel.deployOutpost({
  name: 'analytics',
  hooks: [NavigationHooks.AFTER_EACH],
  handler: ({ verdicts, to }) => {
    trackPageView(to.path);
    return verdicts.ALLOW;
  },
});

An outpost can handle multiple hooks:

typescript
citadel.deployOutpost({
  name: 'admin-only',
  hooks: [NavigationHooks.BEFORE_RESOLVE, NavigationHooks.AFTER_EACH],
  handler: ({ verdicts, hook }) => {
    if (hook === 'beforeResolve') {
      // Check admin role
    }
    if (hook === 'afterEach') {
      // Log admin page view
    }
    return verdicts.ALLOW;
  },
});

🔧 Handler Context

Every outpost handler receives a context object with navigation details:

typescript
interface NavigationOutpostContext {
  verdicts: {
    ALLOW: 'allow';
    BLOCK: 'block';
  };
  to: RouteLocationNormalized; // target route
  from: RouteLocationNormalized; // current route
  router: Router; // router instance
  hook: 'beforeEach' | 'beforeResolve' | 'afterEach';
}

Usage example:

typescript
handler: ({ verdicts, to, from, router, hook }) => {
  // Access route params
  const userId = to.params.id;

  // Access route meta
  const requiresAuth = to.meta.requiresAuth;

  // Check current hook
  if (hook === 'afterEach') {
    // Analytics, logging (return value ignored)
  }

  return verdicts.ALLOW;
};

TIP

When a handler throws an error, the citadel catches it and handles gracefully. See Error Handling for the full error flow, onError, onTimeout, and afterEach behavior.

Diagram Legend
ColorMeaning
🟢Success, ALLOW, continue
🟡Warning, redirect, deduplicate
🔴Error, BLOCK, cancel
🔵Logging (when logger is enabled)
🟣Named debug breakpoint (debug: true)

Released under the MIT License.