Routing & Layouts

FT Configs UI uses TanStack Router with file-based routing. The route tree is generated at build time by @tanstack/router-plugin into src/routeTree.gen.ts from files under src/routes/**.

Layout hierarchy

Layouts are expressed as pathless layout routes (files prefixed with _).

  • src/routes/__root.tsx — root route created via createRootRoute(). Wraps children in <Suspense fallback={<FullPageSpinner/>}><Outlet/></Suspense>. Global providers (I18nProvider, QueryProvider, AuthProvider, RouterProvider, <Toaster/>) live in src/main.tsx / App.tsx, not in the route file.

  • src/routes/_auth.tsxAuthLayout for public pages (flex-centered shell).

  • src/routes/_protected.tsxProtectedLayout. Performs the auth guard via useAuth(): if !isAuthenticated && !isLoading, it calls useNavigate('/login', { replace: true }). It also blocks any route whose path matches DISABLED_ROUTE_PREFIXES by redirecting to /.

  • src/routes/_protected/settings/_admin.tsx — admin sub-layout. Wraps its children in AdminSettingsGuard (role check) and mounts AdminRolesProvider locally (not globally).

The auth guard is implemented at the component level, not via TanStack Router’s beforeLoad. beforeLoad executes outside the React render tree against a frozen snapshot of context, so it cannot wait for AuthProvider to finish its initial refreshSession() call. The component-level guard is the standard SPA pattern documented in the migration plan and is the correct trade-off for this codebase.
beforeLoad is used for static redirects that do not depend on auth state — e.g. /dashboard/, /settings/settings/profile. Throw redirect({ to: '…​' }) from beforeLoad for those cases.

Route tree

Source: src/routes/**. The following tree mirrors the generated routeTree.gen.ts.

src/routes/
├── __root.tsx                          # Root: Suspense + Outlet + FullPageSpinner
├── index.tsx                           # '/' — HomePage (application chooser, lazy)
│
├── _auth.tsx                           # Public layout
│   ├── _auth/login.tsx                 # '/login'
│   ├── _auth/register.tsx              # '/register'
│   └── _auth/change-password.tsx       # '/change-password'
│
└── _protected.tsx                      # Protected layout + auth guard
    ├── _protected/dashboard.tsx        # '/dashboard' → beforeLoad redirects to '/'
    │
    ├── _protected/settings/
    │   ├── index.tsx                   # '/settings' → redirect to SETTINGS_PROFILE
    │   ├── profile.tsx                 # '/settings/profile'
    │   └── _admin.tsx                  # Admin sub-layout (AdminSettingsGuard + AdminRolesProvider)
    │       ├── _admin/users.tsx        # '/settings/users'
    │       ├── _admin/security.tsx     # '/settings/security'
    │       └── _admin/audit-log.tsx    # '/settings/audit-log'
    │
    ├── _protected/acs/                 # 11+ modules: bulk-data, configuration, dashboard,
    │                                   # ctn-info, external-trace, fcc-config, force-qoe-stop,
    │                                   # ftacs-task-config, ftacsws-access, hardcoded-event,
    │                                   # parameter-names-cache, set-parameter-result-template
    │
    ├── _protected/angular/             # 18+ modules: app-ports, columns, cube-dsl-parameters,
    │                                   # custom-params, dashboard, device-activities,
    │                                   # device-monitoring, frames, interface-items, mesh,
    │                                   # neighboring-wifi-diagnostic-paths,
    │                                   # network-device-param-mappings, network-map,
    │                                   # replace-services, rpc-methods, simplified-view,
    │                                   # snmp-configuration, tab-view, tabs, user-info, voip
    │
    ├── _protected/provision-portal/    # 8 modules: index, configuration, csv-settings,
    │                                   # custom-status, objects, params, replace-cpe, statuses
    │
    ├── _protected/northbound.tsx       # '/northbound'
    └── _protected/service-api.tsx      # '/service-api'

High-level route map

Route path constants are centralized in src/lib/constants.ts (APP_ROUTES).

  • / — home (application chooser)

  • /login, /register, /change-password — public auth pages

  • /dashboard — redirects to / (beforeLoad throws redirect)

  • /acs/* — ACS configuration and bulk-data modules

  • /angular/* — Angular Console dictionary modules

  • /provision-portal/* — Provision Portal modules

  • /northbound — Northbound Config editor

  • /service-api — Service API configuration

  • /settings/profile — user preferences

  • /settings/users, /settings/security, /settings/audit-log — admin-only (ADMIN role)

Dynamic routes

TanStack Router uses $param.tsx for dynamic segments (e.g. _protected/replace-services/$id.tsx). Inside the route component, read params via Route.useParams(), typed search params via Route.useSearch() with a validateSearch schema.

Some detail/edit routes are implemented as redirects to list pages with query parameters (example: Replace Services). This pattern is unchanged from the previous implementation — only the routing primitives differ.