Skip to main content

Routing & Guards

Weblisk uses the browser's native navigation (MPA links) rather than client-side routing. But you can add guards and hooks to control navigation behavior.

Route Guards

Protect routes with before/after navigation hooks:

js
import { beforeNavigate, afterNavigate, installGuards } from 'weblisk/nav/guard.js';

// Install the navigation interceptor
installGuards();

// Block unauthenticated access
beforeNavigate((to, from) => {
  if (to.startsWith('/dashboard') && !isLoggedIn()) {
    return '/login'; // Redirect
  }
  return true; // Allow
});

// Warn about unsaved changes
beforeNavigate((to, from) => {
  if (hasUnsavedChanges()) {
    return confirm('You have unsaved changes. Leave?');
  }
});

// Track page views
afterNavigate((to) => {
  analytics.track('pageview', { path: to });
});

Guard Return Values

| Return | Effect |

|--------|--------|

| true | Allow navigation |

| false | Block navigation |

| string | Redirect to that URL |

| Promise | Awaited, then same rules apply |

Scroll Restoration

Save and restore scroll positions across navigations:

js
import { installScroll } from 'weblisk/nav/scroll.js';

installScroll({
  offset: 80,         // Account for sticky header
  savePositions: true, // Remember scroll position per page
});

Manual Control

js
import { saveScroll, restoreScroll, scrollToAnchor } from 'weblisk/nav/scroll.js';

saveScroll('/products');
restoreScroll('/products', 'smooth');
scrollToAnchor('#pricing', 80); // 80px header offset

View Transitions

Smooth page transitions using the View Transitions API:

js
import { navigate, transitionNames } from 'weblisk/nav/transition.js';

// Navigate with a transition
await navigate('/about');

// Navigate with a custom transition type
await navigate('/products', { types: ['slide-left'] });

// Assign transition names for cross-page element matching
transitionNames({
  '.hero-image': 'hero',
  '.page-title': 'title',
});

Falls back to a CSS crossfade on browsers without View Transitions support.

Navigation Interceptor

Upgrade standard MPA link clicks into SPA-style content swaps without changing your HTML:

js
import { intercept } from 'weblisk/nav/router.js';

const router = intercept({
  container: 'main',       // Swap this element's content
  transition: true,        // Use view transitions
  scroll: true,            // Scroll to top after swap
  exclude: ['/api/'],     // Skip these URL patterns
  onNavigate: (url) => console.log('Navigated to', url),
});

// Cleanup
router.destroy();

Uses the Navigation API where available, with click interception + popstate as a fallback. Links with target, download, data-no-intercept, or modifier keys are always left alone.