Routing and App Shell
Introduction
This document describes the current routing model, private route guard, dashboard layout, sidebar behavior, and route extension guidance.
Router Setup
Routing is rendered in src/app/App.tsx, while route definitions and dashboard navigation metadata live in src/app/routes.tsx.
The app tree is:
AlertProvider
`-- BrowserRouter
|-- Routes
| |-- / LoginPage
| |-- /register OrganizationRegistrationPage
| |-- /user-form AdminUserRegistrationPage
| `-- PrivateRoutes
| `-- /dashboard AppShell
| |-- index SensorDashboardPage
| |-- all-sensor SensorListPage
| |-- sensor/:sensorId SensorDetailPage
| |-- organization OrganizationDetailPage
| |-- profile ProfilePage
| |-- user UserListPage
| |-- role RoleListPage
| `-- analytics AnalyticsDashboardPage
|-- Toaster
`-- ConfirmDialog
Route Metadata
src/app/routes.tsx exports:
| Export | Purpose |
|---|---|
publicRoutes | Public route definitions used by App.tsx |
dashboardRoutes | Dashboard route definitions, route titles, nav metadata, and layout variant |
dashboardNavigationItems | Sidebar items derived from dashboard routes |
getDashboardRouteForPath() | Active route lookup used by the app shell |
Dashboard routes can opt into layoutVariant: 'workspace'. Workspace routes, currently analytics, get full-height controlled overflow and no footer.
Public Routes
| Path | Component | Purpose |
|---|---|---|
/ | LoginPage | User login |
/register | OrganizationRegistrationPage | Organization registration |
/user-form | AdminUserRegistrationPage | Admin/user creation after organization registration |
/register and /user-form are public because they are part of onboarding before a session exists.
Private Routes
Private routes are wrapped by PrivateRoutes in src/app/PrivateRoutes.tsx.
const PrivateRoutes: React.FC = () => {
return auth.isAuthenticated() ? <Outlet /> : <Navigate to={ROUTES.LOGIN} replace />;
};
The guard only checks for the access token cookie through auth.isAuthenticated(). It does not validate token expiry or permissions before rendering the route. API calls still handle 401 responses and redirect back to /.
Dashboard Layout
/dashboard renders AppShell from src/core/layout/AppShell.tsx, which owns:
- Desktop sidebar with collapse toggle.
- Mobile drawer using
Sheet. - Current route highlighting.
- Route title lookup from
dashboardRoutes. - User dropdown with profile, organization, language, and logout actions.
- Standard vs workspace content frame rules.
- Nested route rendering through
Outlet.
The dashboard home page is the index route:
/dashboard -> SensorDashboardPage
Sidebar Navigation
The active sidebar menu is derived from dashboardNavigationItems in src/app/routes.tsx:
| Label | Path | Icon |
|---|---|---|
| Dashboard | /dashboard | LayoutDashboard |
| Sensor | /dashboard/all-sensor | Radio |
| Security Analytics | /dashboard/analytics | Activity |
| Role | /dashboard/role | Shield |
| User | /dashboard/user | Users |
The user dropdown exposes additional routes:
| Label | Path |
|---|---|
| Profile | /dashboard/profile |
| Organization | /dashboard/organization |
Page Layout Rules
Route-level dashboard pages should use RoutePage from src/core/page/RoutePage.tsx.
Management pages with table/list workflows should use DataTableCard and domain-specific table partials, for example:
modules/sensors/partials/SensorListTable.tsxmodules/users/partials/UserListTable.tsxmodules/roles/partials/RoleListTable.tsx
Feature-specific visual sections belong in modules/<domain>/partials. A sub-domain folder is used only for larger flows with their own state and UI surface, such as modules/analytics/chat.
Adding a New Dashboard Route
To add a new private dashboard route:
- Create the route-level component under
src/modules/<domain>/pages. - Add reusable domain sections under
src/modules/<domain>/partialswhen needed. - Add modal flows under
src/modules/<domain>/dialogswhen needed. - Import the page in
src/app/routes.tsx. - Add a
dashboardRoutesentry withtitleKey,fullPath, and optional sidebar metadata. - Add any reusable path constant in
src/lib/constants.ts. - Add translation keys if the menu label should be localized.
- Update this documentation if the route becomes part of the stable product surface.