Metronic NextJS
Getting Started

Routing

Learn how to use and customize the routing system in Metronic Next.js.

Routing

Metronic Next.js uses the App Router for handling navigation between different pages. This guide explains the routing system architecture and how to work with it.

Routing Architecture

The App Router in Next.js 15.3 is a file-system based router where:

  1. Folders define the route structure
  2. page.tsx files define UI for a route segment
  3. layout.tsx files define shared UI for a segment and its children
  4. Route Groups (folders with parentheses) organize routes without affecting URL paths

Project Structure

The Metronic Next.js project organizes routes in the app directory:

app/
├── (auth)/                 # Authentication route group (not included in URL)
│   ├── signin/             # Sign-in page
│   ├── signup/             # Sign-up page
│   └── forgot-password/    # Password recovery
├── (protected)/            # Protected routes requiring authentication
│   ├── account/            # Account settings section
│   │   ├── activity/       # Account activity page
│   │   ├── billing/        # Billing page
│   │   └── security/       # Security settings
│   ├── page.tsx            # Dashboard page (default protected route)
│   └── layout.tsx          # Layout for all protected routes
├── api/                    # API routes
│   ├── auth/               # Authentication API endpoints
│   └── [...]/              # Other API endpoints
├── components/             # Shared UI components used across pages
│   ├── layouts/            # Layout components (demo1-demo10)
│   └── ui/                 # UI components
├── models/                 # Data models and interfaces
└── layout.tsx              # Root layout (applies to all pages)

Creating Pages

To create a new page, add a page.tsx file in the appropriate directory:

// Basic page component
export default function AccountPage() {
  return (
    <div>
      <h1>Account Settings</h1>
      <p>Manage your account preferences</p>
    </div>
  );
}

For client-side interactivity, add the 'use client' directive:

'use client';
 
import { useState } from 'react';
 
export default function SettingsPage() {
  const [saved, setSaved] = useState(false);
 
  return (
    <div>
      <h1>Settings</h1>
      {saved && <div>Settings saved!</div>}
      <button onClick={() => setSaved(true)}>Save Settings</button>
    </div>
  );
}

Layouts

Layouts provide a consistent UI structure for route segments:

// Basic layout component
export default function AccountLayout({ children }) {
  return (
    <div className="account-layout">
      <nav className="account-nav">
        {/* Navigation elements */}
      </nav>
      <main>{children}</main>
    </div>
  );
}

The children prop represents the page content or nested layouts.

Route Groups

Route groups, indicated by folders with parentheses, allow you to organize routes without affecting the URL structure:

app/
├── (auth)/       # Authentication routes that don't include "(auth)" in URL
│   ├── signin/   # URL: /signin
│   └── signup/   # URL: /signup
└── (protected)/  # Protected routes that don't include "(protected)" in URL
    └── account/  # URL: /account

Authentication Protection

Create protected layouts that check for authentication:

'use client';
 
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
 
export default function ProtectedLayout({ children }) {
  const { status } = useSession();
  const router = useRouter();
 
  useEffect(() => {
    if (status === 'unauthenticated') {
      router.push('/signin');
    }
  }, [status, router]);
 
  if (status === 'loading') {
    return <div>Loading...</div>;
  }
 
  return status === 'authenticated' ? children : null;
}

For navigation between routes, use the Link component:

import Link from 'next/link';
 
// Basic link
<Link href="/dashboard">Dashboard</Link>
 
// Link with additional props
<Link href="/profile" prefetch={false} className="profile-link">
  Profile
</Link>

Programmatic Navigation

For programmatic navigation (e.g., after form submission), use the useRouter hook:

'use client';
 
import { useRouter } from 'next/navigation';
 
function LoginForm() {
  const router = useRouter();
 
  const handleSubmit = async (e) => {
    e.preventDefault();
    // Login logic...
    router.push('/dashboard');
  };
 
  return <form onSubmit={handleSubmit}>{/* Form fields */}</form>;
}

Dynamic Routes

Create dynamic routes with parameters using brackets in folder names:

app/
└── user/
    └── [id]/
        └── page.tsx  # Matches /user/123, /user/abc, etc.

Access the parameter with the params prop:

export default function UserProfile({ params }) {
  return <div>User ID: {params.id}</div>;
}

Catch-all Routes

For catch-all routes, use triple dots in the folder name:

app/
└── docs/
    └── [...slug]/
        └── page.tsx  # Matches /docs/a, /docs/a/b, /docs/a/b/c, etc.

Access the parameters:

export default function DocsPage({ params }) {
  // slug will be an array, e.g., ['a', 'b', 'c'] for /docs/a/b/c
  return <div>Slug segments: {params.slug.join('/')}</div>;
}

Special Files

Next.js App Router supports several special files:

Loading States

Create a loading.tsx file to show a loading UI:

export default function Loading() {
  return <div>Loading...</div>;
}

Error Handling

Create an error.tsx file to handle errors:

'use client';
 
export default function Error({ error, reset }) {
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={() => reset()}>Try again</button>
    </div>
  );
}

Not Found Pages

Create a not-found.tsx file for 404 errors:

export default function NotFound() {
  return (
    <div>
      <h2>404 - Page Not Found</h2>
      <p>The page you are looking for does not exist.</p>
    </div>
  );
}

Advanced Routing Features

Parallel Routes

For advanced cases, use parallel routes to show multiple pages simultaneously:

// app/layout.tsx
export default function Layout({ children, dashboard, sidebar }) {
  return (
    <div className="layout">
      <div className="sidebar">{sidebar}</div>
      <div className="content">{children}</div>
      <div className="dashboard">{dashboard}</div>
    </div>
  );
}

Intercepting Routes

Use intercepting routes to show UI while keeping the current page, useful for modals:

app/
├── feed/page.tsx           # /feed
└── photo/
    └── (..)feed/[id]/      # Intercepts /photo/123 when navigating from /feed

For more information on App Router features, refer to the Next.js documentation.