This document describes the frontend routing scaffold and the application shell layout for the RHL Lieferscheine app.
Scope (RHL-019):
/login route.Non-goals (out of scope for RHL-019):
The app uses Next.js App Router Route Groups to separate public and protected UI.
Public: app/(public)
/loginProtected: app/(protected)
| URL | Purpose | Notes |
|---|---|---|
/login |
Login placeholder | Public layout (no AppShell) |
/ |
Protected entry placeholder | Later redirects based on session |
/:branch |
Branch placeholder | Example: /NL01 |
/:branch/:year |
Year placeholder | Example: /NL01/2025 |
/:branch/:year/:month |
Month placeholder | Example: /NL01/2025/12 |
/:branch/:year/:month/:day |
Day placeholder | Example: /NL01/2025/12/31 |
/:branch/search |
Search placeholder | Explicit segment so search is not treated as :year |
Important:
/search route. Visiting /search matches /:branch with branch = "search".File: app/layout.jsx
Responsibilities:
app/globals.css).File: app/(public)/layout.jsx
Responsibilities:
/login (and potential future public routes).File: app/(protected)/layout.jsx
Responsibilities:
The AppShell is the stable frame for authenticated UI.
Folder: components/app-shell/*
AppShell.jsx
min-h-screen flex flex-col so the content area can fill remaining height.TopNav.jsx
SidebarPlaceholder.jsx
Later additions:
Admin/dev branch selector
Explorer navigation (year/month/day)
Search filters and shortcuts
UserStatus.jsx
apiClient.getMe()).md:block).Placeholder pages validate:
They render via:
components/placeholders/PlaceholderPage.jsxIn this project setup, dynamic route params can behave like an async value.
Rule of thumb:
[branch], [year], [month], [day]), unwrap params before using properties.To keep the project consistent and avoid test/tooling issues:
Use .jsx for files that contain JSX:
app/**/page.jsx, app/**/layout.jsxcomponents/**Use .js for non-JSX files:
lib/** utilities and helpersapp/api/**/route.jsmodels/**File: lib/frontend/routes.js
Purpose:
Provided helpers:
homePath() → /loginPath() → /loginbranchPath(branch) → /:branchyearPath(branch, year) → /:branch/:yearmonthPath(branch, year, month) → /:branch/:year/:monthdayPath(branch, year, month, day) → /:branch/:year/:month/:daysearchPath(branch) → /:branch/searchlib/frontend/routes.test.js
components/app-shell/AppShell.test.js
next/link is mocked to avoid Next runtime dependency.From the repo root:
npx vitest run
Optional (recommended) build check:
npm run build
Follow Docs/runbook.md.
Typical command:
docker compose -f docker-compose.yml -f docker-compose.local.yml up -d --build
Verify routes:
/login (public layout)/ (protected app shell)/:branch (e.g. /NL01)/:branch/:year/:month/:day (placeholder)/:branch/searchFollow Docs/runbook.md.
Verify:
curl -s http://127.0.0.1:3000/api/healthBrowser:
http(s)://<server>:3000/loginhttp(s)://<server>:3000/NL01/... (or a real branch)/ → /login or /:branch).