Routing¶
All routes are defined in ftl-frontend/src/App.tsx using React Router 7 <Routes>.
Route Table¶
| Path | Guard | Component | Purpose |
|---|---|---|---|
/ |
none | Splash |
Animated loading screen; auto-navigates after ~1.3 s once bootstrap resolves |
/landing |
none | Landing |
Marketing / sign-in entry point |
/register |
none | Register |
3-step Google OAuth registration flow |
/terms |
none | Terms |
Terms of Service (required by Google OAuth consent screen) |
/privacy |
none | Privacy |
Privacy Policy |
/guidelines |
none | Guidelines |
Ranking / conduct guidelines |
/stadium |
RequireAuth |
Stadium |
Match grid and team selector |
/squad |
RequireAuth |
Squad |
Player roster for a selected match side |
/your-team |
RequireAuth |
YourTeam |
Open CFD positions and P&L |
/trade |
RequireAuth |
Trade |
OHLC chart and CFD trade form |
/activity |
RequireAuth |
Activity |
Global / district trade activity feed |
/ranks |
RequireAuth |
Ranks |
Leaderboard (global, district, friends) |
/profile |
RequireAuth |
Profile |
Badges, XP, referral link, tutorial replay |
/invite |
RequireAuth |
InviteFriends |
Share link generator |
/admin |
RequireAdmin |
Admin |
Feature flags, settings, user export, bot controls |
/coming-soon |
RequireAuthOnly |
ComingSoon |
Pre-launch teaser |
/maintenance |
RequireAuthOnly |
Maintenance |
Maintenance notice |
* |
none | <Navigate to="/"> |
Catch-all redirect |
Guard Components¶
RequireAuth¶
Waits for both the auth bootstrap (loaded) and the flags bootstrap (flagsLoaded) to resolve before rendering. Rules applied in order:
- Unauthenticated → redirect to
/landing. maintenance_modeflag is on and user is not admin → redirect to/maintenance.coming_soonflag is on and user is not admin → redirect to/coming-soon.
Admins bypass both flag gates so the admin panel remains reachable in all states.
RequireAuthOnly¶
Waits for auth bootstrap only. Redirects unauthenticated users to /landing. Does not check feature flags.
RequireAdmin¶
Waits for the auth bootstrap (loaded) only — does not wait for flagsLoaded. Checks that a user is present, then adds a role === 'admin' check. Non-admin authenticated users are redirected via getPostAuthPath() (which reads the current flags state) rather than to /landing.
Feature Flag Gates¶
Two flags control pre-launch routing. Both are loaded from /api/flags (public, no auth) on App mount.
| Flag | Effect on non-admin users |
|---|---|
maintenance_mode |
Every RequireAuth-guarded route redirects to /maintenance |
coming_soon |
Every RequireAuth-guarded route redirects to /coming-soon |
maintenance_mode has higher priority than coming_soon. This matches getPostAuthPath() in App.tsx.
Note
/coming-soon and /maintenance use RequireAuthOnly, not RequireAuth. If they used RequireAuth, the guard would see the coming_soon / maintenance_mode flag on its own destination route and redirect back to itself, creating an infinite loop.
Chrome (TopBar + BottomNav)¶
Chrome is hidden for: /, /landing, /register, /terms, /privacy, /guidelines. It is also hidden on /coming-soon and /maintenance for non-admin users — admins keep the chrome so they have a nav path back to /admin to toggle the flag off.
Active Tab Derivation¶
activeTab is derived from location.pathname via the PATH_TO_TAB map. The URL is the single source of truth; setActiveTab calls navigate() and window.scrollTo(0, 0), then refreshes /wallet and /portfolio for the balance pill.