Skip to content

Routing

Carbon Connect uses the Next.js App Router with file-system based routing. All routes are defined in the src/app/ directory.


Route Table

Public Routes

Route Directory Description Auth
/ app/page.tsx Landing page with marketing content No
/login app/login/ Login form (OAuth2 password flow) No
/register app/register/ Registration with tenant creation No
/verify-email app/verify-email/ Email verification callback No

Authenticated Routes

Route Directory Description
/dashboard app/dashboard/page.tsx Dashboard home with stats and activity
/dashboard/grants app/dashboard/grants/ Grant search, filter, and browse
/dashboard/grants/[id] app/dashboard/grants/[id]/ Grant detail view
/dashboard/companies app/dashboard/companies/ Company list and management
/dashboard/companies/[id] app/dashboard/companies/[id]/ Company detail/edit
/dashboard/matches app/dashboard/matches/ Match results with score breakdowns
/dashboard/applications app/dashboard/applications/ Application tracking (Kanban)
/dashboard/applications/[id] app/dashboard/applications/[id]/ Application detail/edit
/dashboard/carbon-profile app/dashboard/carbon-profile/ Carbon profile form (Scope ½/3)
/dashboard/settings app/dashboard/settings/ User and tenant settings
/dashboard/vcri app/dashboard/vcri/ VCRI project management

Layout Structure

Root Layout (app/layout.tsx)

Wraps the entire application:

  • HTML structure with fonts and metadata
  • Theme provider (light/dark mode)
  • React Query provider
  • Toast notification container

Dashboard Layout (app/dashboard/layout.tsx)

Wraps all authenticated pages:

  • Sidebar navigation with route highlighting
  • Top header bar with user menu and notifications
  • Authentication guard (redirects to /login if unauthenticated)
  • Breadcrumb navigation
flowchart TB
    subgraph RootLayout["Root Layout"]
        direction TB
        Providers[QueryClient + Theme]
        subgraph PublicPages["Public Pages"]
            Landing["/"]
            Login["/login"]
            Register["/register"]
        end
        subgraph DashLayout["Dashboard Layout"]
            direction TB
            Sidebar[Sidebar Nav]
            Header[Header Bar]
            subgraph Content["Page Content"]
                Dashboard["/dashboard"]
                Grants["/dashboard/grants"]
                Companies["/dashboard/companies"]
                Matches["/dashboard/matches"]
                Apps["/dashboard/applications"]
                Carbon["/dashboard/carbon-profile"]
                Settings["/dashboard/settings"]
                VCRI["/dashboard/vcri"]
            end
        end
    end

Authentication Guards

The dashboard layout checks for authentication status before rendering:

// app/dashboard/layout.tsx
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
  const { data: user, isLoading } = useCurrentUser();

  // Redirect to login if not authenticated
  if (!isLoading && !user) {
    redirect("/login");
  }

  return (
    <div className="flex h-screen">
      <Sidebar />
      <div className="flex-1 flex flex-col">
        <Header user={user} />
        <main className="flex-1 overflow-auto p-6">
          {children}
        </main>
      </div>
    </div>
  );
}

Token-Based Auth Flow

sequenceDiagram
    participant B as Browser
    participant N as Next.js App
    participant A as API

    B->>N: Navigate to /dashboard
    N->>N: Check localStorage for token
    alt Token exists
        N->>A: GET /api/v1/auth/me
        alt Token valid
            A-->>N: User profile
            N-->>B: Render dashboard
        else Token expired
            A-->>N: 401 Unauthorized
            N->>A: POST /api/v1/auth/refresh
            alt Refresh succeeds
                A-->>N: New tokens
                N->>A: Retry GET /api/v1/auth/me
                A-->>N: User profile
                N-->>B: Render dashboard
            else Refresh fails
                N-->>B: Redirect to /login
            end
        end
    else No token
        N-->>B: Redirect to /login
    end

The sidebar provides navigation for all dashboard sections:

Icon Label Route Description
Home Dashboard /dashboard Overview statistics
Search Grants /dashboard/grants Search and browse grants
Building Companies /dashboard/companies Manage company profiles
Target Matches /dashboard/matches View grant matches
FileText Applications /dashboard/applications Track applications
Leaf Carbon Profile /dashboard/carbon-profile Emission inputs
Settings Settings /dashboard/settings Account settings

Breadcrumb navigation is generated from the URL path segments:

Dashboard > Grants > Horizon Europe Clean Energy

Dynamic Routes

Grant Detail

/dashboard/grants/[id]

Uses Next.js dynamic segments to render individual grant pages. The [id] parameter is a UUID that maps to a grant in the database.

Company Detail

/dashboard/companies/[id]

Application Detail

/dashboard/applications/[id]

API Route Mapping

Frontend routes map to backend API endpoints:

Frontend Route API Endpoint Hook
/dashboard GET /api/v1/dashboard/stats useDashboardStats
/dashboard/grants GET /api/v1/grants/search useGrantSearch
/dashboard/grants/[id] GET /api/v1/grants/{id} useGrant
/dashboard/companies GET /api/v1/companies useCompanies
/dashboard/matches GET /api/v1/matches useMatches
/dashboard/applications GET /api/v1/applications useApplications
/dashboard/carbon-profile GET /api/v1/companies/{id}/carbon-profile useCarbonProfile