# Modules: `src/App.tsx` + `src/main.tsx` > Compact combined doc — both modules are tiny, top-of-tree wiring only. ## `src/main.tsx` (entry) Mounts the React tree: - Calls `createRoot(document.getElementById('root')!)` — the non-null assertion will throw at boot if `
` is missing from `index.html` (it is present). - Wraps in `` (double-renders effects in dev) and `` (HTML5 history). - Imports `./i18n/i18n` for **side effects only** — that file calls `i18n.init({...})` at import time. See `src__i18n__i18n.md` for the locked-language finding (lng:'en' hardcoded). - Imports `./index.css` — the Tailwind 4 stylesheet plus the `az-*` token definitions consumed by every component. No props, no state, nothing testable. ## `src/App.tsx` (route tree) Top-level routes: | Path | Element | Notes | |---|---|---| | `/login` | `` | Public; outside auth + flight providers. | | `/*` | `
...nested Routes...` | Auth-gated container. Mounts `Header` once across all child routes. | | `/flights` | `` | (default redirect target) | | `/annotations` | `` | | | `/dataset` | `` | | | `/admin` | `` | (no extra role gate — see Findings) | | `/settings` | `` | (no extra role gate — see Findings) | | `*` | `` | catch-all under the protected branch. | Outside everything: ``. So: - `LoginPage` can call `useAuth()`. - `FlightProvider` only mounts after `ProtectedRoute` has confirmed an authenticated user — `FlightContext` queries `/api/flights` only once we know we're logged in. This avoids the 401-then-401-loop on first paint. Layout: `flex flex-col h-screen` — header at top, content fills the rest with `overflow-hidden`. Each page owns its own scroll/resize. ## Findings carried into Step 4 / 6 1. **`/admin` is reachable by users without ADM permission (defence-in-depth gap)**: `App.tsx:30` route has no permission check. `Header.tsx:88` filters menu visibility via `hasPermission('ADM')`, but typing `/admin` directly bypasses the menu hide. Users without ADM see a partially-working Admin page until the server returns 403 on each write. Per parent `../../../../_docs/00_roles_permissions.md` only Admin / ApiAdmin holds ADM. **PRIORITY** for Step 4. Note: `/settings` is similarly ungated, but `_docs/00_roles_permissions.md` does NOT define a `SETTINGS` permission code — settings calls land on `/api/admin/...` endpoints which are server-enforced by ADM via 403. Open question for Step 6: should `/settings` also be ADM-gated client-side, or is the per-user-settings subset (`/api/admin/users/me/settings`) intended to be reachable by non-admins? 2. **No `` wrapping the protected branch**: a render error inside any page crashes the whole tree. Step 4 / Step 8. 3. **No lazy-loading of route chunks** (`React.lazy` / `Suspense`). The whole app bundles in one chunk. For now the bundle is small enough that this is acceptable — Step 8 candidate when bundle size grows. 4. **Default redirect target is `/flights`** even for users whose primary task is annotations or dataset. Could be a per-role default landing page. Step 6. (Earlier draft of this doc claimed there was no mobile bottom-nav — that was incorrect. `Header.tsx:113-129` does render a bottom-nav at `< sm`. The whole-app `flex flex-col h-screen` layout is the same at all breakpoints by design.) ## Tests None. ## Cross-doc references - `src__main_tsx` (this doc) ← entry; depended-upon by all others transitively. - `src/auth/AuthContext.tsx`, `src/auth/ProtectedRoute.tsx` — already documented. - `src/components/FlightContext.tsx`, `src/components/Header.tsx` — already documented. - Parent roles spec: `../../../../_docs/00_roles_permissions.md`.