Routing
This document explains the routing system used in the Rhesis frontend application, which is built with Next.js App Router.
App Router Overview
The Rhesis frontend uses Next.js App Router, which provides a file-system based routing approach where:
- Folders define routes
- Files define UI
- Special files handle specific functionality (layout, page, loading, etc.)
- Dynamic segments are supported with brackets notation
Route Structure
The main route structure is organized as follows:
Route Groups
Route groups are used to organize routes without affecting the URL structure. In our application, we use route groups for:
(protected)
: Pages that require authentication(public)
: Pages that are publicly accessible
Layouts
Layouts are used to share UI between multiple pages. Our application uses several levels of layouts:
-
Root Layout (
app/layout.tsx
): Applied to all pages, contains:- Theme provider
- Global styles
- Top-level metadata
-
Auth Layout (
app/auth/layout.tsx
): Applied to authentication pages, contains:- Centered card layout
- Brand elements
- No navigation
-
Protected Layout (
app/(protected)/layout.tsx
): Applied to authenticated pages, contains:- Authentication check
- Main navigation (sidebar)
- Header
- User menu
Navigation
Link Component
For client-side navigation, use the Next.js Link
component:
Programmatic Navigation
For programmatic navigation, use the useRouter
hook:
Route Protection
Routes under the (protected)
route group are protected by authentication middleware:
- Middleware Check: The
middleware.ts
file checks for authentication on protected routes - Session Validation: If no valid session exists, the user is redirected to the login page
- Role-Based Access: Some routes may have additional role-based access controls
Dynamic Routes
Dynamic routes use parameters in the URL, defined with brackets notation:
/projects/[id]
: Project detail page, where[id]
is the project identifier/tests/[id]
: Test detail page, where[id]
is the test identifier
Access parameters in the page component:
Loading States
Loading states are defined using special loading.tsx
files:
// app/(protected)/projects/loading.tsx
export default function Loading() {
return <div>Loading projects...</div>;
}
Error Handling
Error states are defined using special error.tsx
files:
// app/(protected)/projects/error.tsx
'use client';
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={reset}>Try again</button>
</div>
);
}
Not Found Pages
Not found pages are defined using special not-found.tsx
files:
// app/(protected)/projects/[id]/not-found.tsx
export default function NotFound() {
return <div>Project not found</div>;
}
Metadata
Page metadata is defined using the metadata
export:
// app/(protected)/projects/page.tsx
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Projects | Rhesis',
description: 'Manage your Rhesis projects',
};
export default function ProjectsPage() {
// ...
}
Best Practices
- Keep Pages Thin: Page components should focus on data fetching and layout, with most UI logic in components
- Use Server Components: Leverage server components for data fetching where possible
- Client Components: Use the
'use client'
directive only when needed for interactivity - Parallel Routes: Use parallel routes for complex layouts with independent navigation
- Intercepting Routes: Use intercepting routes for modals and overlays