Now.js Framework Documentation

Now.js Framework Documentation

RouterManager

EN 29 Nov 2025 03:12

RouterManager

Now.js Router Manager - Manage routing and navigation in Single Page Applications (SPA)

Overview

RouterManager is a core component of Now.js that handles routing and navigation, supporting both hash-based routing (#/path) and history API (/path) with authentication guards, middleware, and route parameter extraction.

Use Cases:

  • Single Page Application (SPA) routing
  • Dynamic content loading without page refresh
  • URL parameter and query string handling
  • Route guards and authentication
  • Nested routes and route groups
  • Customizable 404 error handling

Browser Compatibility:

  • Chrome, Firefox, Safari, Edge (modern versions)
  • History API support for modern browsers
  • Hash mode fallback for older browsers

Installation and Initialization

Loading the Script

RouterManager is included in Now.js core:

<script src="/Now/Now.js"></script>

Or load separately:

<script src="/Now/js/RouterManager.js"></script>

Basic Initialization

// Simple router initialization
await RouterManager.init({
    enabled: true,
    mode: 'history', // 'hash' or 'history'
    base: '/'
});

// Register routes
RouterManager.register('/home', {
    template: 'home',
    title: 'Home Page'
});

RouterManager.register('/about', {
    template: 'about',
    title: 'About Us'
});

Initialization via Now.js

await Now.init({
    router: {
        enabled: true,
        mode: 'history',
        base: '/',
        notFound: {
            path: '/404',
            template: '404',
            title: 'Page Not Found'
        }
    }
});

Configuration Options

Main Options

Option Type Default Description
enabled boolean false Enable router
mode string 'history' Routing mode: 'hash' or 'history'
base string '/' Application base path
autoDetectBase boolean true Auto-detect base path from script location
fallback string 'index.html' Fallback page for 404
showLoadingNotification boolean true Show loading notification

Auth Configuration

auth: {
    enabled: false,              // Enable auth guards
    autoGuard: true,             // Auto-protect routes by conventions
    defaultRequireAuth: false,   // Require auth for all routes by default
    publicPaths: ['/login', '/register'],
    guestOnlyPaths: ['/login', '/register'],
    conventions: {
        '/auth/*': { public: true },
        '/admin/*': { roles: ['admin'] }
    },
    redirects: {
        unauthorized: '/login',
        forbidden: '/403',
        afterLogin: '/',
        afterLogout: '/login'
    }
}

Not Found Configuration

notFound: {
    path: '/404',           // Route path for 404
    template: '404',        // Template for 404 page
    title: 'Page Not Found',
    behavior: 'render',     // 'render', 'redirect', 'silent'
    preserveUrl: false,     // Preserve original URL
    preserveQuery: true,    // Preserve query string
    customHandler: null     // Custom handler function
}

Initial Load Configuration

initialLoad: {
    enabled: true,              // Handle initial page load
    preserveContent: false,     // Preserve existing content
    skipIfContent: true,        // Skip if content exists
    contentSelector: '#main',   // Selector to check for content
    forceRoute: false          // Force route even with content
}

Trailing Slash Configuration

trailingSlash: {
    mode: 'remove',        // 'remove', 'add', 'preserve'
    redirect: false,       // Redirect when handling trailing slash
    ignorePaths: ['/']     // Paths to ignore trailing slash handling
}

Methods and Properties

init(options)

Initialize RouterManager with configuration

Parameters:

  • options (Object, optional) - Configuration options

Return: (Promise) - Resolves when initialization completes

Usage Examples:

// Basic initialization
await RouterManager.init({
    enabled: true,
    mode: 'history'
});

// With auth enabled
await RouterManager.init({
    enabled: true,
    mode: 'history',
    auth: {
        enabled: true,
        defaultRequireAuth: true,
        publicPaths: ['/login', '/register', '/']
    }
});

// With custom 404 handler
await RouterManager.init({
    enabled: true,
    notFound: {
        behavior: 'redirect',
        path: '/404',
        customHandler: (path) => {
            console.log('Page not found:', path);
        }
    }
});

register(path, config)

Register a route in the router

Parameters:

  • path (string) - Route path supporting parameters like /user/:id
  • config (Object|string) - Route configuration or template name

Configuration Object:

  • template (string) - Template path or HTML string
  • title (string, optional) - Page title
  • guards (Array, optional) - Route guards
  • requireAuth (boolean, optional) - Require authentication
  • roles (Array, optional) - Required roles
  • public (boolean, optional) - Public route (no auth needed)
  • children (Object, optional) - Nested routes

Return: void

Usage Examples:

// Simple route
RouterManager.register('/home', 'home');

// Route with config
RouterManager.register('/about', {
    template: 'about',
    title: 'About Us'
});

// Route with parameters
RouterManager.register('/user/:id', {
    template: 'user-profile',
    title: 'User Profile'
});

// Protected route
RouterManager.register('/dashboard', {
    template: 'dashboard',
    title: 'Dashboard',
    requireAuth: true
});

// Route with roles
RouterManager.register('/admin', {
    template: 'admin',
    title: 'Admin Panel',
    requireAuth: true,
    roles: ['admin']
});

// Route with inline template
RouterManager.register('/info', {
    template: '<div><h1>Info Page</h1><p>Information content</p></div>',
    title: 'Information'
});

// Route with nested routes
RouterManager.register('/docs', {
    template: 'docs-layout',
    title: 'Documentation',
    children: {
        '/getting-started': {
            template: 'docs-getting-started',
            title: 'Getting Started'
        },
        '/api': {
            template: 'docs-api',
            title: 'API Reference'
        }
    }
});

Navigate to specified route

Parameters:

  • path (string) - Route path
  • params (Object, optional) - Route parameters
  • options (Object, optional) - Navigation options
    • replace (boolean) - Use replaceState instead of pushState
    • skipGuards (boolean) - Skip guards
    • preserveQuery (boolean) - Preserve existing query string

Return: (Promise) - Resolves when navigation completes

Usage Examples:

// Basic navigation
await RouterManager.navigate('/home');

// Navigate with parameters
await RouterManager.navigate('/user/:id', { id: 123 });

// Navigate with query string
await RouterManager.navigate('/search?q=keyword');

// Replace current history entry
await RouterManager.navigate('/about', {}, { replace: true });

// Navigate programmatically
document.getElementById('btn').addEventListener('click', () => {
    RouterManager.navigate('/contact');
});

// Navigate with params object
await RouterManager.navigate('/product/:category/:id', {
    category: 'electronics',
    id: 'laptop-001'
});
// Result: /product/electronics/laptop-001

beforeEach(guard)

Add global guard that runs before every route navigation

Parameters:

  • guard (Function) - Guard function (to, from, next) => {}
    • to (Object) - Target route information
    • from (Object) - Current route information
    • next (Function) - Call to continue or pass path to redirect

Return: (Function) - Unregister function

Usage Examples:

// Log navigation
RouterManager.beforeEach((to, from, next) => {
    console.log(`Navigating from ${from.path} to ${to.path}`);
    next();
});

// Authentication guard
RouterManager.beforeEach(async (to, from, next) => {
    const requireAuth = to.route?.requireAuth;
    const isAuthenticated = await checkAuth();

    if (requireAuth && !isAuthenticated) {
        next('/login');
    } else {
        next();
    }
});

// Role-based guard
RouterManager.beforeEach(async (to, from, next) => {
    const requiredRoles = to.route?.roles;

    if (requiredRoles) {
        const userRoles = await getUserRoles();
        const hasRole = requiredRoles.some(role => userRoles.includes(role));

        if (!hasRole) {
            next('/forbidden');
            return;
        }
    }

    next();
});

// Unregister guard
const unregister = RouterManager.beforeEach((to, from, next) => {
    // Guard logic
    next();
});

// Later...
unregister(); // Remove this guard

afterEach(guard)

Add global guard that runs after every route navigation

Parameters:

  • guard (Function) - Guard function (to, from) => {}

Return: (Function) - Unregister function

Usage Examples:

// Page view tracking
RouterManager.afterEach((to, from) => {
    if (window.gtag) {
        gtag('config', 'GA_MEASUREMENT_ID', {
            page_path: to.path
        });
    }
});

// Scroll to top
RouterManager.afterEach(() => {
    window.scrollTo(0, 0);
});

// Update breadcrumb
RouterManager.afterEach((to) => {
    updateBreadcrumb(to.path);
});

// Close mobile menu
RouterManager.afterEach(() => {
    const mobileMenu = document.querySelector('.mobile-menu');
    if (mobileMenu) {
        mobileMenu.classList.remove('open');
    }
});

getPath(includeQuery)

Get current path

Parameters:

  • includeQuery (boolean, optional) - Include query string

Return: (string) - Current path

Usage Examples:

// Get path without query
const path = RouterManager.getPath();
console.log(path); // Output: /user/123

// Get path with query
const fullPath = RouterManager.getPath(true);
console.log(fullPath); // Output: /user/123?tab=profile

// Check current route
if (RouterManager.getPath() === '/admin') {
    console.log('On admin page');
}

getQuery()

Get current query string

Return: (string) - Query string including ?

Usage Examples:

// URL: /search?q=laptop&category=electronics
const query = RouterManager.getQuery();
console.log(query); // Output: ?q=laptop&category=electronics

// Parse query string
const params = new URLSearchParams(RouterManager.getQuery());
console.log(params.get('q')); // Output: laptop
console.log(params.get('category')); // Output: electronics

getParams()

Get all route parameters

Return: (Object) - Parameters object

Usage Examples:

// URL: /user/123
// Route: /user/:id
const params = RouterManager.getParams();
console.log(params.id); // Output: 123

// URL: /product/electronics/laptop-001
// Route: /product/:category/:id
const params = RouterManager.getParams();
console.log(params.category); // Output: electronics
console.log(params.id); // Output: laptop-001

getParam(name)

Get route parameter by name

Parameters:

  • name (string) - Parameter name

Return: (string|undefined) - Parameter value

Usage Examples:

// URL: /user/123
// Route: /user/:id
const userId = RouterManager.getParam('id');
console.log(userId); // Output: 123

// Check if parameter exists
const categoryId = RouterManager.getParam('categoryId');
if (categoryId) {
    loadCategory(categoryId);
}

hasRoute(path)

Check if route exists

Parameters:

  • path (string) - Route path

Return: (boolean)

Usage Examples:

if (RouterManager.hasRoute('/admin')) {
    console.log('Admin route exists');
}

// Conditional navigation
const targetPath = '/dashboard';
if (RouterManager.hasRoute(targetPath)) {
    RouterManager.navigate(targetPath);
} else {
    RouterManager.navigate('/404');
}

getRoute(path)

Get route configuration

Parameters:

  • path (string) - Route path

Return: (Object|undefined) - Route configuration

Usage Examples:

const route = RouterManager.getRoute('/dashboard');
console.log(route.title); // Output: Dashboard
console.log(route.requireAuth); // Output: true

// Check route properties
const aboutRoute = RouterManager.getRoute('/about');
if (aboutRoute) {
    console.log('Template:', aboutRoute.template);
    console.log('Title:', aboutRoute.title);
}

getRoutes()

Get all routes

Return: (Array) - Array of route objects

Usage Examples:

const allRoutes = RouterManager.getRoutes();
allRoutes.forEach(route => {
    console.log(`${route.path} - ${route.title}`);
});

// Generate navigation menu
const routes = RouterManager.getRoutes();
const menuItems = routes
    .filter(route => !route.hidden)
    .map(route => ({
        path: route.path,
        title: route.title
    }));

State Properties

RouterManager has a state object storing current state:

RouterManager.state = {
    current: null,      // Current route object
    previous: null,     // Previous route object
    initialized: false, // Initialization status
    loading: false,     // Loading status
    error: null,        // Error object (if any)
    disabled: false     // Disabled status
}

Usage Examples:

// Check if initialized
if (RouterManager.state.initialized) {
    console.log('Router is ready');
}

// Check loading state
if (RouterManager.state.loading) {
    console.log('Navigation in progress...');
}

// Check current route
console.log('Current route:', RouterManager.state.current?.path);
console.log('Previous route:', RouterManager.state.previous?.path);

// Check for errors
if (RouterManager.state.error) {
    console.error('Router error:', RouterManager.state.error);
}

Practical Examples

Example 1: Basic SPA Setup

// Initialize router
await RouterManager.init({
    enabled: true,
    mode: 'history',
    base: '/'
});

// Register routes
RouterManager.register('/', {
    template: 'home',
    title: 'Home'
});

RouterManager.register('/about', {
    template: 'about',
    title: 'About Us'
});

RouterManager.register('/contact', {
    template: 'contact',
    title: 'Contact'
});

// HTML links
// <a href="/about">About</a>
// <a href="/contact">Contact</a>

Example 2: Protected Routes with Authentication

// Initialize with auth
await RouterManager.init({
    enabled: true,
    auth: {
        enabled: true,
        defaultRequireAuth: false,
        publicPaths: ['/login', '/register', '/'],
        redirects: {
            unauthorized: '/login'
        }
    }
});

// Public routes
RouterManager.register('/', {
    template: 'home',
    title: 'Home',
    public: true
});

RouterManager.register('/login', {
    template: 'login',
    title: 'Login',
    public: true
});

// Protected routes
RouterManager.register('/dashboard', {
    template: 'dashboard',
    title: 'Dashboard',
    requireAuth: true
});

RouterManager.register('/profile', {
    template: 'profile',
    title: 'My Profile',
    requireAuth: true
});

// Admin only route
RouterManager.register('/admin', {
    template: 'admin',
    title: 'Admin Panel',
    requireAuth: true,
    roles: ['admin']
});

Example 3: Dynamic Routes with Parameters

// User profile route
RouterManager.register('/user/:id', {
    template: 'user-profile',
    title: 'User Profile'
});

// Product detail route
RouterManager.register('/product/:category/:id', {
    template: 'product-detail',
    title: 'Product Details'
});

// Blog post route
RouterManager.register('/blog/:slug', {
    template: 'blog-post',
    title: 'Blog Post'
});

// Navigate with params
RouterManager.navigate('/user/:id', { id: 123 });
RouterManager.navigate('/product/:category/:id', {
    category: 'electronics',
    id: 'laptop-001'
});
RouterManager.navigate('/blog/:slug', { slug: 'hello-world' });

// Access params in template
const userId = RouterManager.getParam('id');
const category = RouterManager.getParam('category');
const productId = RouterManager.getParam('id');

Example 4: Custom Navigation Guards

// Loading indicator guard
RouterManager.beforeEach((to, from, next) => {
    // Show loading
    document.body.classList.add('loading');
    next();
});

RouterManager.afterEach(() => {
    // Hide loading
    document.body.classList.remove('loading');
});

// Permission check guard
RouterManager.beforeEach(async (to, from, next) => {
    if (to.route?.requireAuth) {
        const authManager = Now.getManager('auth');

        if (!authManager.isAuthenticated()) {
            next('/login');
            return;
        }

        if (to.route.roles) {
            const hasPermission = await authManager.hasAnyRole(to.route.roles);
            if (!hasPermission) {
                next('/forbidden');
                return;
            }
        }
    }

    next();
});

// Analytics tracking
RouterManager.afterEach((to, from) => {
    // Google Analytics
    if (window.gtag) {
        gtag('config', 'GA_MEASUREMENT_ID', {
            page_path: to.path,
            page_title: to.route?.title
        });
    }

    // Custom analytics
    trackPageView(to.path);
});

Example 5: Hash Mode Setup

// Initialize in hash mode
await RouterManager.init({
    enabled: true,
    mode: 'hash',  // URLs will be like: /#/path
    base: '/'
});

// Register routes (same as history mode)
RouterManager.register('/home', 'home');
RouterManager.register('/about', 'about');

// URLs will be:
// http://example.com/#/home
// http://example.com/#/about

// Navigation works the same
RouterManager.navigate('/home');

Example 6: Custom 404 Handler

await RouterManager.init({
    enabled: true,
    notFound: {
        behavior: 'render',
        template: 'custom-404',
        title: '404 - Page Not Found',
        preserveUrl: true,
        customHandler: (path) => {
            console.log('404 - Path not found:', path);

            // Log to analytics
            if (window.gtag) {
                gtag('event', 'page_not_found', {
                    page_path: path
                });
            }

            // Suggest similar pages
            suggestSimilarPages(path);
        }
    }
});

Events and Callbacks

RouterManager works with EventManager by emitting various events:

router:before-navigate

Fired before navigation starts

Now.getManager('event').on('router:before-navigate', (data) => {
    console.log('Navigating to:', data.path);
    console.log('Parameters:', data.params);
});

router:after-navigate

Fired after successful navigation

Now.getManager('event').on('router:after-navigate', (data) => {
    console.log('Navigation complete');
    console.log('Current route:', data.to);
    console.log('Previous route:', data.from);
});

router:error

Fired when navigation error occurs

Now.getManager('event').on('router:error', (error) => {
    console.error('Navigation error:', error);
});

router:not-found

Fired when route not found

Now.getManager('event').on('router:not-found', (data) => {
    console.log('Route not found:', data.path);
});

router:auth-redirect

Fired when redirected due to authentication

Now.getManager('event').on('router:auth-redirect', (data) => {
    console.log('Auth redirect:', data.reason);
    console.log('From:', data.from);
    console.log('To:', data.to);
});

Best Practices

✓ Do's

  • ✓ Use history mode for production (cleaner URLs)
  • ✓ Use hash mode for development or when server configuration is not possible
  • ✓ Set correct base path when app is not at root
  • ✓ Use route parameters for dynamic content
  • ✓ Configure appropriate 404 handler
  • ✓ Use guards for authentication and authorization
  • ✓ Clearly separate public and protected routes
  • ✓ Use meaningful template names
  • ✓ Use async/await for navigation and guards
  • ✓ Handle errors appropriately
  • ✓ Use Events for tracking and analytics

✗ Don'ts

  • ✗ Don't hard-code URLs in code, use navigate() instead
  • ✗ Don't forget server rewrite configuration for history mode
  • ✗ Don't use window.location.href for navigation
  • ✗ Don't forget to call next() in beforeEach guards
  • ✗ Don't block navigation too long in guards
  • ✗ Don't use query strings for sensitive data
  • ✗ Don't create circular redirects
  • ✗ Don't forget to handle async operations in guards

Tips and Recommendations

  1. Server Configuration for History Mode

    • Apache: Use .htaccess to redirect all requests to index.html
    • Nginx: Use try_files $uri $uri/ /index.html
  2. Route Organization

    • Group routes by feature
    • Use nested routes for complex layouts
    • Separate public and protected routes
  3. Performance

    • Use lazy loading for large templates
    • Cache frequently used templates
    • Optimize guards for fast execution
  4. Security

    • Use auth guards for protected routes
    • Validate parameters in guards
    • Don't rely solely on client-side routing

Common Pitfalls

❌ Wrong: Using window.location.href for navigation

// ❌ Wrong - causes page reload
document.querySelector('#link').addEventListener('click', () => {
    window.location.href = '/about';
});

✅ Right: Use RouterManager.navigate()

// ✅ Right - SPA navigation
document.querySelector('#link').addEventListener('click', () => {
    RouterManager.navigate('/about');
});

❌ Wrong: Forgetting to call next() in guard

// ❌ Wrong - Navigation will stop
RouterManager.beforeEach((to, from, next) => {
    console.log('Navigating...');
    // Forgot to call next()
});

✅ Right: Always call next()

// ✅ Right
RouterManager.beforeEach((to, from, next) => {
    console.log('Navigating...');
    next(); // Must call
});

❌ Wrong: History mode without server configuration

// ❌ Wrong - Direct URLs will cause 404 errors
await RouterManager.init({
    mode: 'history'
});
// But no server rewrite rule

✅ Right: Configure server rewrite

# .htaccess for Apache
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>
// ✅ Right - Now direct URLs will work
await RouterManager.init({
    mode: 'history'
});

❌ Wrong: Blocking guard too long

// ❌ Wrong - Guard takes too long
RouterManager.beforeEach(async (to, from, next) => {
    // Slow API call
    await fetch('/api/slow-endpoint');
    await new Promise(resolve => setTimeout(resolve, 5000));
    next();
});

✅ Right: Optimize guard performance

// ✅ Right - Do only what's necessary
RouterManager.beforeEach(async (to, from, next) => {
    // Check cache first
    if (isCached()) {
        next();
        return;
    }

    // Quick validation only
    const isValid = await quickCheck();
    next(isValid ? undefined : '/error');
});

❌ Wrong: Not handling missing parameters

// ❌ Wrong - May cause undefined errors
RouterManager.register('/user/:id', {
    template: 'user-profile'
});

// In template
const userId = RouterManager.getParam('id');
loadUser(userId); // userId might be undefined

✅ Right: Validate parameters

// ✅ Right - Validate before use
RouterManager.register('/user/:id', {
    template: 'user-profile'
});

const userId = RouterManager.getParam('id');
if (!userId) {
    RouterManager.navigate('/404');
} else {
    loadUser(userId);
}

// Or use guard
RouterManager.beforeEach((to, from, next) => {
    if (to.path.startsWith('/user/') && !to.params.id) {
        next('/404');
    } else {
        next();
    }
});

Performance Considerations

Performance Optimization

  1. Template Caching

    // Templates are cached automatically
    // But can be preloaded
    RouterManager.register('/dashboard', {
       template: 'dashboard',
       preload: true
    });
  2. Lazy Loading

    // Load template only when needed
    RouterManager.register('/heavy-page', {
       template: async () => {
           const module = await import('./templates/heavy-page.js');
           return module.template;
       }
    });
  3. Route Guards Optimization

    // Cache auth check results
    let authCache = null;
    let cacheTime = 0;
    
    RouterManager.beforeEach(async (to, from, next) => {
       const now = Date.now();
    
       // Use cache if fresh (5 seconds)
       if (authCache && (now - cacheTime < 5000)) {
           next(authCache ? undefined : '/login');
           return;
       }
    
       // Check auth
       authCache = await checkAuth();
       cacheTime = now;
    
       next(authCache ? undefined : '/login');
    });

Considerations

  • Navigation frequency: Don't navigate too frequently (debounce if needed)
  • Guard complexity: Guards should be fast (< 100ms)
  • Template size: Use lazy loading for large templates
  • Memory leaks: Unregister event listeners when done

Security Considerations

Security Considerations

  1. Client-Side Security

    // ❌ Don't rely only on client-side protection
    RouterManager.register('/admin', {
       requireAuth: true,
       roles: ['admin']
    });
    
    // ✅ Must have server-side validation too
    // Server must verify authentication and authorization
  2. XSS Protection

    // ✅ RouterManager escapes HTML automatically
    // But be careful when using innerHTML directly
    
    // ✓ Safe
    const params = RouterManager.getParams();
    element.textContent = params.name;
    
    // ✗ Dangerous
    element.innerHTML = params.name; // Possible XSS
  3. Parameter Validation

    // ✅ Validate parameters
    RouterManager.beforeEach((to, from, next) => {
       if (to.params.id) {
           // Validate ID format
           if (!/^\d+$/.test(to.params.id)) {
               next('/404');
               return;
           }
       }
       next();
    });
  4. CSRF Protection

    // For forms submitted via router
    // Use CSRF token
    RouterManager.beforeEach(async (to, from, next) => {
       if (to.route?.requiresCSRF) {
           const token = await getCSRFToken();
           to.params._csrf = token;
       }
       next();
    });

Browser Compatibility

Supported Browsers

Browser Version Mode Support
Chrome Latest 2 versions Hash, History
Firefox Latest 2 versions Hash, History
Safari Latest 2 versions Hash, History
Edge Latest 2 versions Hash, History
iOS Safari iOS 12+ Hash, History
Chrome Android Latest Hash, History

Polyfills

For older browsers:

<!-- History API polyfill -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=URL,history"></script>

Known Issues

  1. iOS Safari Back Button: May have issues with history.back() on older iOS Safari

    • Solution: Use hash mode or update iOS
  2. IE11: Partial History API support

    • Solution: Use hash mode or polyfill

TemplateManager

AuthManager

EventManager

HistoryManager

  • Manages browser history
  • Back/Forward navigation

Additional Notes

Supported Versions

  • Now.js v1.0+
  • ES6+ JavaScript

Breaking Changes

v1.0:

  • Changed API from callback-based to Promise-based
  • init() must be awaited
  • Guards support async/await

Deprecation Notices

  • RouterManager.route() - Use register() instead
  • RouterManager.go() - Use navigate() instead

Limitations

  1. Router works client-side only
  2. Server configuration needed for history mode
  3. SEO: Use SSR or prerendering for better SEO
  4. Query parameters have length limits per browser

API Reference

Complete methods list:

Method Parameters Return Description
init(options) Object Promise Initialize router
register(path, config) String, Object void Register route
navigate(path, params, options) String, Object, Object Promise Navigate to route
beforeEach(guard) Function Function Add before guard
afterEach(guard) Function Function Add after guard
getPath(includeQuery) Boolean String Get current path
getQuery() - String Get query string
getParams() - Object Get all parameters
getParam(name) String String Get parameter by name
hasRoute(path) String Boolean Check if route exists
getRoute(path) String Object Get route config
getRoutes() - Array Get all routes

Complete Project Example

// main.js - SPA with authentication
(async () => {
    // Initialize Now.js with Router
    await Now.init({
        router: {
            enabled: true,
            mode: 'history',
            base: '/',
            auth: {
                enabled: true,
                defaultRequireAuth: false,
                publicPaths: ['/login', '/register', '/'],
                redirects: {
                    unauthorized: '/login',
                    afterLogin: '/dashboard'
                }
            },
            notFound: {
                template: '404',
                title: 'Page Not Found'
            }
        }
    });

    const router = Now.getManager('router');

    // Public routes
    router.register('/', {
        template: 'home',
        title: 'Home',
        public: true
    });

    router.register('/login', {
        template: 'login',
        title: 'Login',
        public: true
    });

    router.register('/register', {
        template: 'register',
        title: 'Register',
        public: true
    });

    // Protected routes
    router.register('/dashboard', {
        template: 'dashboard',
        title: 'Dashboard',
        requireAuth: true
    });

    router.register('/profile', {
        template: 'profile',
        title: 'My Profile',
        requireAuth: true
    });

    router.register('/settings', {
        template: 'settings',
        title: 'Settings',
        requireAuth: true
    });

    // Admin routes
    router.register('/admin', {
        template: 'admin',
        title: 'Admin Panel',
        requireAuth: true,
        roles: ['admin']
    });

    // Dynamic routes
    router.register('/user/:id', {
        template: 'user-profile',
        title: 'User Profile',
        requireAuth: true
    });

    // Global guards
    router.beforeEach((to, from, next) => {
        console.log(`Navigating: ${from.path} → ${to.path}`);
        next();
    });

    router.afterEach((to, from) => {
        // Analytics
        if (window.gtag) {
            gtag('config', 'GA_ID', {
                page_path: to.path
            });
        }

        // Scroll to top
        window.scrollTo(0, 0);
    });
})();