Skip to content

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:

  1. Unauthenticated → redirect to /landing.
  2. maintenance_mode flag is on and user is not admin → redirect to /maintenance.
  3. coming_soon flag 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.