Routing in Nijor

Nijor utilizes a modern file-based routing system. Routes are automatically generated based on the file and folder hierarchy located inside the src/pages directory. Each .nijor file inside this folder compiles into a distinct application route.

This declarative, convention-over-configuration model eliminates the need to manually register, configure, or maintain a centralized routing file.

Basic Routing

Every standard file in the src/pages directory maps directly to a URL route path:


        src/pages/
            index.nijor
            about.nijor
    

This structure generates the following URL endpoints:


        index.nijor  -> / (Home Page)
        about.nijor  -> /about
    

If a visitor navigates to a URL that does not map to a page, Nijor will automatically render the fallback error page located at src/pages/404.nijor.

Nested Routing

Creating subdirectories inside src/pages naturally organizes your application into nested paths and route structures:


        src/pages/
            blog/
                index.nijor
                [slug].nijor
    

This directory structure compiles into the following nested routes:


        blog/index.nijor   -> /blog
        blog/[slug].nijor  -> /blog/:slug
    

Parameterized (Dynamic) Routing

Dynamic paths are defined by wrapping a parameter name in square brackets [paramName] inside the filename.


        src/pages/products/[id]/[name].nijor
    

This route matches dynamic paths such as /products/123/phone. Dynamic parameters are made available to the page through the params attribute in the <template> block (unlike components which use props).


        <body params="{ id, name }">
            <h1>Product: {name}</h1>
            <p>Product ID: {id}</p>
            <button on:click="buy('{id}')">Purchase {name}</button>
        </body>

        <script>
            export function buy(id) {
                alert("Purchasing product: " + id);
            }
        </script>
    

Route parameters can be accessed directly in the template and are available inside your <script> scope. However, do not reference route parameters directly inside inline event function signatures; instead, pass them as arguments explicitly.

Layouts

Layouts define the shared, structural shell used across different pages. Common layout elements include navigation bars, sidebars, headers, and footers.

Layouts are stored in the src/layouts folder. Every Nijor application must have a default layout at src/layouts/default.nijor, which wraps every page by default.

Layouts identify where the dynamic page content should be injected using the special n:slot attribute.

Example Layout : src/layouts/default.nijor


        <body>
            <nav>
                <a n:route="/">Home</a> | 
                <a nroute="/about">About Us</a>
            </nav>

            <!-- Page content is loaded inside the slot below -->
            <div n:slot></div>
        </body>
    

A page can specify a custom layout by adding the layout attribute to its <template>:


        <body layout="dashboard">
            <h1>Welcome to the Admin Portal</h1>
        </body>
    

This snippet instructs Nijor to render the page inside src/layouts/dashboard.nijor. If the layout attribute is omitted, Nijor defaults back to default.nijor.

Client-Side Navigation

To enable smooth, single-page application (SPA) transitions without reloading the page, use the n:route attribute on your anchor tags. Standard href attributes still work, but they trigger a full browser page refresh.


        <a n:route="/dashboard">Dashboard</a> <!-- Smooth SPA client-side navigation -->
        <a href="/dashboard">Dashboard</a>  <!-- Triggers full browser refresh -->
    

Use n:route for internal paths, and stick to standard href for external websites.

Link Prefetching

Nijor automatically prefetches visible route links on the viewport to optimize page transition performance. When a link featuring n:route enters the user's viewport, its route bundles are loaded in the background, making transitions nearly instantaneous when clicked.

If a route loads extensive datasets or you want to save network bandwidth, you can opt-out of prefetching for specific links using the no-prefetch attribute:


        <a n:route="/heavy-dashboard" no-prefetch>Admin Dashboard</a>
    

Route Lifecycle : onRoute

Nijor provides an onRoute() lifecycle hook to execute code whenever a client-side navigation occurs. This callback is ideal for tracking analytics, triggering page-view side effects, or updating global application state.


        import { onRoute } from "nijor/router";

        onRoute(route => {
            console.log("Navigated to: " + route);
            // e.g., trigger Google Analytics page views
        });
    

Page Metadata & Head Tag

Nijor pages can feature a custom <head> block (using the <nhead> tag inside code templates) to manage page-specific metadata such as titles, keywords, and description tags.

The title metadata operates dynamically in both client-side rendering (CSR) and server-side rendering (SSR), and supports route parameters:


        <head>
            <title>{name} | Store</title>
            <meta name="description" content="Explore  specifications.">
        </head>

        <body params="{ id, name }">
            <h1>Product: {name}</h1>
            <p>ID: {id}</p>
        </body>
    

Advanced : Understanding App.js

The file src/App.js is the official entry point of a Nijor web application. Nijor is versatile: you can run a Nijor app both with or without routing.

(1) Standard Setup with Routing

When utilizing file-based routing, App.js initializes the router and includes the compiler-utilized //@Routes() directive, which dynamically injects pages and layouts at compile time.


        import { Render } from "nijor/core";
        import "nijor/router";

        //@Routes()

        (async () => await Render(document.getElementById('app')))();
    

(2) Advanced Routing with App.nijor

If you want your layouts to share persistent components (such as a global header, floating side panel, or theme toggler), you can register a root component called App.nijor.

Replace <div id="app"></div> inside your index.html with <app></app>, and configure App.js as follows :


        import { Render } from "nijor/core";
        import "nijor/router";
        import App from "@/App.nijor";

        //@Routes()

        (async () => {
            await App.run('app', 1);
            await Render(document.getElementById('app')) // Move <div id="app"></div> inside App.nijor
        })();
    

(3) Setup Without Routing

For single-page applications or simple widgets that do not require navigation, you can bypass the router entirely. Replace <div id="app"></div> in your index.html with <app></app>, and bootstrap your root component directly:


        import App from "@/App.nijor";

        (async () => await App.run('app', 1))();
    

Component Bootstrapping Mechanics

Every compiled Nijor component exposes a native run() method. The run function targets and initializes elements by their tags:


        Component.run(tagName, count);
    

The tagName defines which element is targetable, and count determines how many matching DOM occurrences should be swapped out. Under normal development circumstances, the Nijor compiler handles this bootstrapping sequence automatically.