# Frontend System Audit (Full)

| Field | Value |
|-------|-------|
| Date | 2025-11-05 |
| Scope | `apps/web` (Vue 3 + Quasar SPA) |
| Sources | `apps/web/src/app/main.ts`, `apps/web/src/modules/*`, `docs/REFERENCE.md` |
| Owner | Frontend platform |

## Stack Snapshot
| Layer | File(s) | Responsibilities | Notes |
|-------|---------|------------------|-------|
| Bootstrap & Observability | `apps/web/src/app/main.ts`<br>`apps/web/src/services/api.ts` | Creates Vue app, registers Pinia, Quasar, i18n, VueApexCharts, Sentry, navigation/service orchestrators; attaches auth interceptor and background `initializeAsync` for auth + planner session | `__APP_TESTING__` harness exposed in E2E mode; `apiClient` blocks mutating calls when offline, stamps `Authorization` per async token + redirects 401s to `/login` |
| Shell & Layout | `apps/web/src/app/App.vue`<br>`apps/web/src/app/components/AppShell.vue` | Global header/drawer/mobile nav, NotificationCenter, theme toggle, quick actions, offline banners/dialogs | `AppShell` swaps desktop nav vs mobile tab rail, provides action-sheet FAB; NotificationCenter consumes smart notifications + event bus for spotlight |
| Routing & Responsiveness | `apps/web/src/app/router.ts`<br>`apps/web/src/app/responsivePageLoader.ts`<br>`apps/web/src/app/components/NetworkStatus.vue` | Defines guarded routes, responsive loaders (desktop vs mobile) with `MOBILE_ONLY_RUNTIME`, scroll behavior, and net-status overlays | Prefetches modules on hover/focus, enforces `requiresAuth`/`requiresAdmin`, exposes network + sync health via `useSyncQueue` |
| State & Persistence | `apps/web/src/modules/planner/stores/plannerStore.ts`<br>`apps/web/src/modules/map/stores/mapStore.ts`<br>`apps/web/src/shared/utils/storage.ts` | Pinia stores per domain, persisted plan/map context, safe `localStorage` helpers with SSR/browsing guards | Planner store merges API payloads with cached stages/segments and remembers last plan; Map store keeps `planContext` + routing preferences under `map.*` keys |
| Offline & Sync | `apps/web/src/modules/offline/services/indexedDBService.ts`<br>`apps/web/src/modules/offline/services/syncQueueService.ts`<br>`apps/web/src/modules/offline/stores/offlineStore.ts` | Dexie schema for plans + sync queue, adaptive queue processor (10s→60s) with exponential backoff and ID reconciliation, offline store dashboards | Queue remaps plan/stage temp IDs, emits reconciliation events, exposes inspector + manual retry, hooks `networkQualityService` |
| CRDT Collaboration | `apps/web/src/modules/collab/services/syncService.ts`<br>`apps/web/src/workers/indexedDBWorkerClient.ts` | Maintains Y.Doc per plan, persists updates via worker, syncs every 10s (battery/activity aware) and polls presence | Debounced sync (1s), battery + user-activity driven intervals (10s/30s/60s), worker shields UI thread while reading/writing IndexedDB |
| Mapping Stack | `apps/web/src/modules/map/components/MapView.vue`<br>`apps/web/src/modules/map/services/mapboxMapsService.ts`<br>`apps/web/src/modules/map/composables/useMapbox.ts` | Mapbox GL renderer, MapPreset layouts, AI/map panels, offline map hooks, MapPlanContext bridging | Requires `VITE_MAPBOX_TOKEN/_ACCESS_TOKEN`; Mapbox service adds Draw/Geocoder + CSS-var theming, composable surfaces token errors + loading states |
| AI & Analytics | `apps/web/src/modules/ai/stores/aiStore.ts`<br>`apps/web/src/modules/ai/services/aiService.ts`<br>`apps/web/src/modules/planner/components/DashboardAIAssistant.vue` | AI client for six endpoints with cache key builder, quota tracking, usage insights + dashboard charts | Emits `ai:*` events for orchestrator, caches suggestions 5 min by lat/lng/categories/prompt, exposes overview/queue stats to dashboards |
| Auth & Identity | `apps/web/src/modules/auth/stores/authStore.ts`<br>`apps/web/src/modules/auth/services/authService.ts`<br>`apps/web/src/services/firebase.ts` | Auth0 SPA bootstrap, claim parsing (roles/subscription), mock adapters for E2E, `/api/auth` fetchers with retry/backoff, optional Firebase guards | Honors `VITE_E2E_AUTH_BYPASS`, stores locale + last redirect safely, `authorizedFetch` respects `Retry-After`, Firebase init fails fast when keys missing |
| Gamification & Rewards | `apps/web/src/services/orchestrator.ts`<br>`apps/web/src/services/rewardService.ts`<br>`apps/web/src/modules/gamification/services/gamificationHandlers.ts`<br>`apps/web/src/modules/gamification/stores/gamificationStore.ts` | Routes planner/AI/offline events to reward rules, emits `reward:process`/`points:earned`, updates gamification store (profile, leaderboard, fuel, quests) | Controlled via `VITE_GAMIFICATION_STAGE_REWARDS/AI_REWARDS/OFFLINE_REWARDS`; store logs rank/level progress and hooks UI badges/leaderboards |

## Routing Map
| Route | Path | Loader | Guards | Notes |
|-------|------|--------|--------|-------|
| Landing | `/` | Direct import `@modules/planner/pages/LandingPage.vue` | Public | Hosts marketing hero + SocialFeed preview with guest mode |
| Dashboard | `/dashboard` | `responsivePageLoader(DashboardPage.mobile.vue, DashboardPage.web.vue)` | `requiresAuth` | Primary hub with analytics widgets, AISuggestions, Live map snapshot |
| Planner | `/planner/:id?` | `responsivePageLoader(PlannerPage.mobile.vue, PlannerPage.web.vue)` | `requiresAuth` | Full editor with timeline/stage lists; `PlanView` route redirects here |
| Map | `/map` | `responsivePageLoader(MapPage.mobile.vue, MapPage.web.vue)` | `requiresAuth` | Dedicated Mapbox experience (presets, AI assistant, offline manager) |
| Explore | `/explore` | `responsivePageLoader(ExplorePage.mobile.vue, ExplorePage.web.vue)` | Public | Discovery surface backed by `publicPlannerStore` |
| Leaderboard | `/leaderboard` | `responsivePageLoader(LeaderboardPage.mobile.vue, LeaderboardPage.web.vue)` | `requiresAuth` | Gamification rankings + badge grid |
| Search | `/search` | `responsivePageLoader(SearchPage.mobile.vue, SearchPage.vue)` | `requiresAuth` | Global POI search with filters/favorites |
| Settings | `/settings/:tab?` | `responsivePageLoader(SettingsPage.mobile.vue, SettingsPage.vue)` | `requiresAuth` | Houses tabs (profile, billing, gamification) incl. `/gamification` redirect |
| Profile | `/profile` | `responsivePageLoader(ProfilePage.mobile.vue, ProfilePage.web.vue)` | `requiresAuth` | User profile editing + avatar selection |
| Subscriptions | `/subscriptions` | Direct `@modules/billing/pages/SubscriptionsPage.vue` | `requiresAuth` | Stripe plan management & referral leaderboard |
| Auth | `/login`, `/register`, `/callback` | `responsivePageLoader(AuthPage.mobile.vue, AuthPage.web.vue)` | Public | Shared auth page toggles by query; `/register` ensures `mode=signup` |
| Admin | `/admin` + children | `responsivePageLoader(AdminPage.mobile.vue, modules/admin/AdminLayout.vue)` | `requiresAuth` + `requiresAdmin` | Nested views (dashboard/users/content/settings/moderation/gamification/billing/health/cache/audit) |
| Map redirect | `/plan/:id` | Route redirect to `PlanEditor` | `requiresAuth` | Preserves old deep links to new planner |
| Not Found | `/:catchAll(.*)*` | `@/pages/NotFound.vue` | Public | Generic 404 with action buttons |

## Core Modules
| Domain | Key UI | Store(s) | Service(s) | Highlights |
|--------|--------|----------|------------|------------|
| planner | `pages/DashboardPage.mobile.vue`, `.web.vue`, `LandingPage.vue`, `PlannerPage.mobile.vue`, `.web.vue`, ~43 components (`PlanCard.vue`, `StageList.vue`, `PlannerWizardWeb.vue`, `PlannerConfigurationPanel.vue`, `controllers/VoiceController.vue`, map controls) | `modules/planner/stores/plannerStore.ts` | `modules/planner/services/plannerService.ts`, `plannerSession.ts`, `mapboxService.ts`, `weatherService.ts` | Handles plan CRUD with offline merging + Dexie caching, emits `plan:*`/`stage:*` events, keeps dashboard insights (`PlannerInsights`, `PlannerDashboardSnapshot`) and preferences synced |
| map | `pages/MapPage.mobile.vue`, `.web.vue`, `components/MapView.vue`, `MapActionStack.vue`, `MapPresetLayout.vue`, `MapSegmentInsightsCard.vue`, mobile sheets (`POIBottomSheet.vue`, `StageListSheet.vue`) | `modules/map/stores/mapStore.ts` | `modules/map/services/mapboxMapsService.ts`, `advancedRoutingService.ts`, `mapVisualizationService.ts`, `osrmRoutingService.ts`, `weatherService.ts` | Stores `MapPlanContext` + routing prefs in safe storage, exposes 39+ components (filters, HUD, AI panels), integrates Mapbox Draw/Geocoder, supports offline map downloads + voice commands |
| ai | `components/SuggestionsList.vue`, `AIQuotaDisplay.vue`, planner `AISuggestionsPanel.vue` | `modules/ai/stores/aiStore.ts` | `modules/ai/services/aiService.ts` | Provides suggestion cache keyed by lat/lng/categories/prompt/context, polls `/api/ai/jobs/:jobId`, tracks usage/quota/insights, emits `ai:suggestion:*` and `ai:generation:*` events |
| collab | `components/CommentsSection.vue`, `CommentItem.vue`, `ShareDialog.vue` | `modules/collab/stores/collabSharingStore.ts` | `modules/collab/services/syncService.ts`, `collabSharingService.ts` | Uses Yjs doc persisted via worker, HTTP sync `/api/collab/sync/:planId`, polls `/presence`, battery/activity tuned intervals, share dialog hits `/api/sharing` to create invite links |
| offline | `shared/components/OfflineStatusBanner.vue`, `OfflineQueueDialog.vue`, `app/components/NetworkStatus.vue` | `modules/offline/stores/offlineStore.ts` | `modules/offline/services/indexedDBService.ts`, `syncQueueService.ts`, `networkQualityService.ts`, `syncQueue.ts` | Dexie stores plans + queue actions, `useSyncQueue` exposes pending/failed ops, adaptive 10s→60s cadence, queue emits reconciliation + updates Quasar banners/dialog |
| gamification | `pages/LeaderboardPage.mobile.vue`, `.web.vue`, `components/BadgeGrid.vue`, `LeaderboardTable.vue`, `ProfileCard.vue`, `StatsCard.vue` | `modules/gamification/stores/gamificationStore.ts` | `modules/gamification/services/gamificationService.ts`, `gamificationHandlers.ts`, `bingoService.ts` | Fetches `/api/gamification/*`, computes rank/level/fuel, handles quests + badge normalization, listens to `reward:process` and emits `points:earned` |
| live | `components/CreateSessionDialog.vue`, `JoinSessionDialog.vue`, `LiveChat.vue`, `LiveParticipantsList.vue`, `EmergencyButton.vue`, `NavigationHUD.vue` | `modules/live/stores/liveNavigationStore.ts` | `modules/live/services/liveNavigationService.ts`, `geolocationService.ts` | REST-only polling (session 10s, chat 4s), manages sessions/participants/telemetry/emergency alerts, uses Geolocation service for tracked positions |
| social | `components/SocialFeed.vue` | `modules/social/stores/liveSocialStore.ts` | `modules/social/services/liveSocialService.ts`, `clanService.ts` | Toggles overlays for friends/clans using API-provided `refreshIntervalMs`, schedules independent timers, fetches clan memberships + trending activity |
| location | (Consumed by map/mobile HUD) | `modules/location/stores/locationTrackingStore.ts` | `modules/location/services/locationService.ts` | Watches browser geolocation, batches updates (30s sync, 10s batch delay) with safeLocalStorage queue, flushes on network regain, exposes summary metrics |

## Supporting Modules
| Domain | Key UI | Store(s) | Service(s) | Highlights |
|--------|--------|----------|------------|------------|
| auth | `pages/AuthPage.mobile.vue`, `.web.vue`, `components/LoginForm.vue`, `SignUpForm.vue` | `modules/auth/stores/authStore.ts` | `modules/auth/services/authService.ts`, `authMockAdapter.ts`, composables `useAuth.ts`, `useAuthPageController.ts`, `useSessionMonitor.ts` | Auth0 SPA client with AuthZ claims, e2e bypass option, `authorizedFetch` adds retries + `ResolveApiPath`; persists locale + login hints |
| billing | `pages/SubscriptionsPage.mobile.vue`, `.vue`, `components/BillingPlanCard.vue` | `modules/billing/stores/billingStore.ts` | `modules/billing/services/billingService.ts` | Fetches plans/summary/usage/referrals, creates checkout/portal sessions via `/api/billing/*`, logs telemetry for debugging |
| admin | `pages/AdminPage.mobile.vue`, `AdminLayout.vue`, `views/*`, widgets (`AdminSidebar.vue`, `StatCard.vue`, `HealthHistoryChart.vue`, `ServiceComparison.vue`) | `modules/admin/stores/adminStore.ts` | `modules/admin/services/adminService.ts`, `adminRewardService.ts` | Uses `resolveApiPath('/api/admin')`, supplies moderation, cache, plan, badge/quest/challenge, season config tooling with mock latency + cloning helpers |
| notifications | `app/components/NotificationCenter.vue` | (Composable) `modules/notifications/composables/useNotifications.ts` | `modules/notifications/services/notificationsService.ts` | Polls `/api/notifications` every 30s (list) + 10s (unread), auto-toasts new items, gracefully falls back to local mock data when API missing |
| explore | `pages/ExplorePage.mobile.vue`, `.web.vue` | `modules/explore/stores/publicPlannerStore.ts` | `modules/explore/composables/useExplorePageController.ts` | Loads `/api/planner/plans/public`, tracks loading/error, powers discovery grid and map preview |
| search | `pages/SearchPage.mobile.vue`, `.vue` | `modules/search/stores/searchStore.ts` | `modules/search/services/searchService.ts` | Maintains filters (categories, price, distance, ratings), debounced remote search `/api/search`, handles favorites + selection |
| profile | `pages/ProfilePage.mobile.vue`, `.web.vue`, `components/IconSelector.vue` | `modules/profile/stores/profileStore.ts` | `modules/profile/services/profileService.ts`, `avatarService.ts` | Edits user preferences + avatar uploads, syncs with `/api/auth/me`, leverages Auth store data |
| settings | `pages/SettingsPage.mobile.vue`, `.vue`, sections (`BillingSection.vue`, `GamificationSection.vue`, `PreferencesSection.vue`, `ProfileSection.vue`, `SecuritySection.vue`) | `modules/settings/stores/localSettingsStore.ts` | `modules/settings/composables/useSettingsActions.ts`, `useSettingsViewModel.ts` | Persists devMode + local UI toggles, routes tab query params, surfaces billing/gamification/profile panes in single hub |

## Shared Layer & UI Toolkit
| Category | Files | Responsibilities | Notes |
|----------|-------|------------------|-------|
| Shared components | `apps/web/src/shared/components/*` (BaseButton, BaseCard, BaseChart, BaseIcon, PageShell, QuickActionsFAB, OfflineIndicator, OfflineQueueDialog, OfflineStatusBanner, OperationStatus, RetryButton, SyncStatusBadge, CollaborativeCursors, ui/Spinner) | Common UI primitives, offline banners/dialogs, status badges, skeleton shells | Imported across modules; align with design tokens and Quasar overrides for consistent theming |
| UI kit + mobile atoms | `apps/web/src/components/ui/*.vue`, `apps/web/src/components/mobile/*.vue`, `apps/web/src/components/ThemeToggle.vue`, `apps/web/src/components/UiBackgroundFX*.vue` | Glass cards, floating panels, timelines, search bars, mobile dialogs/toasts, theme switcher, ambient FX | Provides cohesive look for dashboards/mobile pages; theme toggle ties into Quasar dark/auto modes |
| Shared composables | `apps/web/src/shared/composables/useFormValidation.ts`, `useLocaleNumber.ts`, `useMobileStatusSignals.ts`, `useSmartNotifications.ts` | Cross-module helpers for validation, localized formatting, mobile HUD signals, toasts linked to NotificationCenter | Used by planner, notifications, Dashboard UI; centralizes UX patterns |
| Shared utilities | `apps/web/src/shared/utils/format.ts`, `storage.ts`, `logger.ts`, `profileIcons.ts`, `apps/web/src/utils/date-i18n.ts`, `apps/web/src/utils/haptics.ts` | Formatting helpers, safe storage wrappers, namespaced logger factory, icon registry, date/i18n and haptics utilities | `createLogger` gives module-prefixed console logs, storage helpers guard SSR/private modes |
| Worker layer | `apps/web/src/workers/indexedDBWorkerClient.ts` (+ `indexeddb.worker.ts`) | Non-blocking persistence for CRDT state + Dexie access via postMessage | Used by collaboration + offline modules to keep main thread responsive |

## Cross-Cutting Systems
| System | Files | Purpose | Behavior |
|--------|-------|---------|----------|
| Event Bus | `apps/web/src/services/eventBus.ts` | Typed pub/sub for planner, AI, gamification, offline, navigation, admin, notifications | Registers dozens of events (`plan:*`, `ai:*`, `reward:*`, `navigation:*`, `admin:*`), returns unsubscribe handles, logs when `import.meta.env.DEV` |
| Service Orchestrator | `apps/web/src/services/orchestrator.ts` | Wires planner/AI/offline events to `rewardService`, gamification handlers, sharing hooks | Init at startup, honors `VITE_GAMIFICATION_*` toggles, listens for plan/stage create/update/complete + AI events and emits reward events |
| Reward Engine | `apps/web/src/services/rewardService.ts`, `apps/web/src/services/rewardConfig.ts`, `apps/web/src/modules/gamification/services/gamificationHandlers.ts` | Calculates points/fuel/xp per event + emits/consumes `reward:process` / `points:earned` | Configurable rules with local overrides, deduplicates batch events, gamification handlers convert reward contexts into UI updates |
| Navigation Bridge | `apps/web/src/services/navigationBridge.ts` | Converts event bus intents (`navigation:go`, `planner:open`, `map:open`, `explore:open`) into router pushes | Normalizes params/query, prevents duplicate navigations, allows `replace`/`force`, used by NotificationCenter + quick actions |
| Planner Session Bridge | `apps/web/src/modules/planner/services/plannerSession.ts`, `apps/web/src/modules/map/stores/mapStore.ts`, `apps/web/src/modules/offline/stores/offlineStore.ts` | Keeps planner store, map context, offline cache aligned | Watches planner current plan/stage, updates map context + caches plan offline, reacts to map-driven context changes to load/switch plans |
| Offline Monitoring | `apps/web/src/modules/offline/stores/offlineStore.ts`, `apps/web/src/shared/components/OfflineStatusBanner.vue`, `apps/web/src/shared/components/OfflineQueueDialog.vue`, `apps/web/src/app/components/NetworkStatus.vue` | Surface queue health, manual sync, failed ops, online status | Auto-refreshes queue/stats, exposes Quasar banners/dialogs, allows retries + clearing failed actions |
| Live Location & Social | `apps/web/src/modules/location/stores/locationTrackingStore.ts`, `apps/web/src/modules/live/stores/liveNavigationStore.ts`, `apps/web/src/modules/social/stores/liveSocialStore.ts` | Track device geolocation, live navigation sessions, overlays for friends/clans | Uses geolocation watch + safeLocalStorage queue, HTTP polling for sessions/chat/social overlays, respects user toggles |
| Notifications Center | `apps/web/src/modules/notifications/composables/useNotifications.ts`, `apps/web/src/app/components/NotificationCenter.vue` | Poll + display notifications, mark read, drive navigation | 30s/10s polling cadences, emits smart toasts on new entries, uses event bus + `navigationBridge` for CTA routing |

## Data Flow Bridges
| Flow | Files | Input → Output | Details |
|------|-------|----------------|---------|
| Planner ↔ Map context | `modules/planner/services/plannerSession.ts`, `modules/map/stores/mapStore.ts`, `modules/planner/components/map/*.vue` | Planner store changes → Map context + offline cache; Map context (source `map`) → Planner stage selection | Watchers cache plans, propagate stage focus, auto-activate plan when user selects from map, ensures `mapStore.planContext` stays authoritative |
| Sync queue reconciliation | `modules/planner/services/plannerService.ts`, `modules/offline/services/syncQueueService.ts`, `modules/offline/services/indexedDBService.ts` | Offline actions enqueued → API calls (create/update/delete/stage ops) → Dexie reconciled data | Adaptive retry/backoff, remaps temp IDs, emits `plan:reconciled` / `stage:reconciled`, removes queue entries on success |
| Gamification rewards | `services/orchestrator.ts`, `services/rewardService.ts`, `modules/gamification/services/gamificationHandlers.ts`, `modules/gamification/stores/gamificationStore.ts` | Planner/AI/offline events → reward calculation → gamification store updates | Rewards respect config + env toggles, handlers emit points/fuel + future badge hooks, store recomputes leaderboard rank/progress |
| Notifications-driven navigation | `modules/notifications/composables/useNotifications.ts`, `app/components/NotificationCenter.vue`, `services/navigationBridge.ts` | Polled notifications + click handlers → mark read → event bus nav intents | `onNotificationClick` marks read, chooses destination (plan, dashboard, etc.), uses `navigation:go` events so router guards apply |
| Live telemetry & chat | `modules/live/services/liveNavigationService.ts`, `modules/live/stores/liveNavigationStore.ts`, `modules/live/components/LiveChat.vue` | Poll `/api/live/sessions/*` + chat endpoints → update store → UI lists & HUD | Session + chat listeners keep `lastSession/lastMessageKey`, dedupe updates, degrade to min 5s intervals to honor "HTTP polling only" constraint |

## Offline, Polling & Collaboration Cadence
| Capability | Files | Interval / Trigger | Details |
|------------|-------|--------------------|---------|
| Planner Sync Queue | `modules/offline/services/syncQueueService.ts`, `modules/planner/services/plannerService.ts` | Auto process every 10s when busy, slows to 60s when idle; per-action backoff 1s→30s | Remaps plan/stage IDs post-sync, subscribes offline store for live stats, stops when navigator offline |
| Network Quality Detector | `modules/offline/services/networkQualityService.ts`, `modules/offline/stores/offlineStore.ts` | Checks immediately + every 60s (or manual force) | Hits `/health`, categorizes fast/slow/offline, recommends sync interval for queue + UI |
| Collaboration Sync | `modules/collab/services/syncService.ts` | Base 10s; extends to 30s/60s per battery + user inactivity; 1s debounce on state changes | Uses Yjs updates persisted via worker, triggers immediate sync on online/plan switch |
| Notifications Polling | `modules/notifications/composables/useNotifications.ts` | Full list ↔ 30s, unread count ↔ 10s | Known IDs tracked for new-item toasts, fallback dataset returned when API missing |
| Live Navigation Polling | `modules/live/services/liveNavigationService.ts` | Sessions default 10s (min 5s), chat 4s | Each subscription manages timers + stop handles, respects refresh interval downgrades |
| Live Social Overlays | `modules/social/stores/liveSocialStore.ts` | Default 15s per overlay; updated via API `refreshIntervalMs` | Separate timers for friends/clan; toggles disable timers, network errors logged + surfaced |
| Location Tracking & Sync | `modules/location/stores/locationTrackingStore.ts` | Geolocation watch; batch queue flush every 30s with 10s delay, retries every 30s on failure | Persists queue in safeLocalStorage (`LOCATION_QUEUE_STORAGE_KEY`), flushes immediately when network returns |

## Styling & Theming
| Layer | Files | Purpose | Notes |
|-------|-------|---------|-------|
| Design tokens | `apps/web/src/styles/design-tokens.css` | Canonical colors, spacing, typography, theme vars | Imported first in `main.ts` to feed Quasar + Mapbox CSS var helpers |
| Base & Shared styles | `apps/web/src/styles/base.scss`, `apps/web/src/styles/shared-components.css`, `apps/web/src/styles/buttons.css` | Reset + shared utility classes, glass surfaces, accent-aware buttons | Provide consistent look for shared components + modules |
| Quasar overrides | `apps/web/src/styles/quasar-overrides.css`, `apps/web/src/styles/quasar-accent-override.css` | Align Quasar components with tokens, override accent behavior (brand colors) | Must load after Quasar CSS to take effect |
| Theme controls | `apps/web/src/components/ThemeToggle.vue`, header theme button in `App.vue` | Switch between dark/light/auto modes via Quasar brand config | Theme button uses `currentTheme` and Quasar dark API |
| Map styling | `modules/planner/components/map/MapStyleSwitcher.vue`, `modules/map/services/mapboxMapsService.ts` | Mapbox styles/thumbnails, CSS-var-driven draw colors | Requires Mapbox tokens, uses CSS vars (`--map-accent`) for on-brand layers |
| FX layers | `apps/web/src/components/UiBackgroundFX.vue`, `UiBackgroundFXDevPanel.vue` | Animated background + dev tuning panel | Optional but keeps brand visuals consistent across landing/dashboard |

## Internationalization, Testing & Tooling
| Capability | Files | Purpose | Notes |
|------------|-------|---------|-------|
| i18n | `apps/web/src/i18n/index.ts`, `apps/web/src/locales/en.json`, `apps/web/src/locales/fr.json` | Dual-locale messaging (fr default, en fallback) | Locale pulled from user preferences or safeLocalStorage fallback |
| E2E/Test harness | `apps/web/src/app/main.ts` | Provides `globalThis.__APP_TESTING__` with Pinia + seed helpers when `MODE==='e2e'` | Enables automated tests to preload planner data + access stores |
| Unit tests | `apps/web/src/modules/planner/stores/__tests__/plannerStore.test.ts`, `modules/planner/services/__tests__/plannerSession.test.ts`, `modules/gamification/stores/__tests__/gamificationStore.test.ts` | Regression coverage for core stores/services | Run via `pnpm test`; ensures planner/gamification logic stays deterministic |
| Charts/Analytics | `apps/web/src/app/main.ts` (VueApexCharts), `apps/web/src/modules/planner/components/DashboardAIAssistant.vue`, `apps/web/src/modules/admin/components/*Chart.vue` | Global chart plugin + dashboards for planner/admin insights | Centralized plugin avoids duplicate imports and ensures SSR-safe registration |

## Feature Flags & Environment
| Flag | Defined In | Controls | Notes |
|------|------------|----------|-------|
| `VITE_API_URL` / `VITE_API_BASE_URL` / `VITE_API_ENDPOINT` | `apps/web/src/services/api.ts` | API base URL resolution + `resolveApiPath` helper | Falls back to `http://localhost:3000` server-side; trims trailing slashes |
| `VITE_SENTRY_DSN` | `apps/web/src/app/main.ts` | Enables Sentry tracing + replay | When absent, Sentry init skipped entirely |
| `VITE_ENABLE_DESKTOP` | `apps/web/src/app/responsivePageLoader.ts` | Forces mobile variant in production when false (`MOBILE_ONLY_RUNTIME`) | Lets product ship mobile-only experience even on desktop widths |
| `VITE_MAPBOX_TOKEN` / `VITE_MAPBOX_ACCESS_TOKEN` | `modules/map/components/MapView.vue`, `modules/map/composables/useMapbox.ts`, `modules/planner/components/map/MapStyleSwitcher.vue` | Mapbox GL access + thumbnail rendering | Missing token logs explicit error + blocks map init |
| Auth0 config (`VITE_AUTH0_DOMAIN`, `VITE_AUTH0_CLIENT_ID`, `VITE_AUTH0_AUDIENCE`, `VITE_AUTH0_SCOPE`, `VITE_AUTH0_ROLES_CLAIM`, `VITE_AUTH0_REDIRECT_URI`) | `modules/auth/stores/authStore.ts` | SPA auth client, claim parsing, callback URL | Defaults to `openid profile email offline_access` scope and custom roles claim if unset |
| `VITE_E2E_AUTH_BYPASS` | `modules/auth/stores/authStore.ts`, `modules/gamification/stores/gamificationStore.ts` | Enables mock auth bundle + bypass gamification fuel gating during tests | Also read from `globalThis.__E2E_AUTH_BYPASS__` |
| `VITE_NETWORK_HEALTH_CHECK_URL` / `VITE_DISABLE_NETWORK_HEALTH_CHECK` | `modules/offline/services/networkQualityService.ts` | Overrides the network-health probe target or disables the HTTP check entirely | Default `/api/health`; disabling (often in tests) makes the detector trust `navigator.onLine` so builds without API access still behave as 'fast' |
| Gamification toggles (`VITE_GAMIFICATION_STAGE_REWARDS`, `VITE_GAMIFICATION_AI_REWARDS`, `VITE_GAMIFICATION_OFFLINE_REWARDS`) | `apps/web/src/services/orchestrator.ts` | Selectively register reward listeners for stage/AI/offline events | Allows staged rollout of reward types |
| Firebase keys (`VITE_FIREBASE_*`) | `apps/web/src/services/firebase.ts` | Optional Firebase Auth/Firestore/Storage clients | When incomplete, service disables itself and throws descriptive error |
