--- type: architecture title: Frontend Structure description: Angular routes, components, services, guards, interceptors, and authenticated SSE transport. tags: [architecture, frontend, angular, shell, sse] timestamp: 2026-07-22T09:35:00Z --- # Routes Routes live in `frontend/src/app/app.routes.ts`: | Path | Component | Guard | Notes | |---|---|---|---| | `/bootstrap` | `SetupCreateAdminComponent` | — | First-admin creation flow. | | `/login` | `LandingComponent` | `landingGuard` | Public landing and authentication modal. | | `/` | `HomeComponent` | `authGuard` | Authenticated shell and child outlet. | | `/challenges` | `ChallengesPage` | inherited | Placeholder challenges page. | | `/scoreboard` | `ScoreboardPage` | inherited | Placeholder scoreboard page. | | `/blog` | `BlogPage` | inherited | Placeholder blog page. | | `/admin` | `AdminUsersComponent` | `adminGuard` | Admin-only child route. | # Components and services | Symbol | Path | Responsibility | |---|---|---| | `HomeComponent` | `frontend/src/app/features/home/home.component.ts` | Smart shell; owns navigation signals, user hydration, change-password flow, and event-stream lifecycle. | | `ShellHeaderComponent` | `frontend/src/app/features/shell/header/shell-header.component.ts` | Renders title, active section, event LED/countdown, and user menu; contains component-scoped LED styling. | | `QuickTabsComponent` | `frontend/src/app/features/shell/tabs/quick-tabs.component.ts` | Emits navigation events for Challenges, Scoreboard, and Blog. | | `EventStatusStore` | `frontend/src/app/core/services/event-status.store.ts` | Applies event state frames and computes countdown text; re-exports the pure LED color mapping. | | `AuthenticatedEventSourceService` | `frontend/src/app/core/services/authenticated-event-source.service.ts` | Opens authenticated SSE over `fetch`, parsing streamed frames into `EventSourceLike` events. | | `AuthService` | `frontend/src/app/core/services/auth.service.ts` | Stores the access token used by the authenticated SSE transport. | | `UserStore` | `frontend/src/app/core/services/user.store.ts` | Hydrates the signed-in user and rank data. | # Authenticated SSE wiring `HomeComponent.ngOnInit()` calls `EventStatusStore.start()` with a factory for `AuthenticatedEventSourceService.open('/api/v1/events/status')`. The transport: 1. Reads the access token from `AuthService`. 2. Sends `Accept: text/event-stream`, optional `Authorization: Bearer `, `credentials: 'include'`, and an `AbortSignal`. 3. Reads the response body with a stream reader and decodes UTF-8 chunks. 4. Splits complete SSE records on blank lines, joins repeated `data:` lines, and dispatches `MessageEvent` objects. 5. Buffers records received before the message listener is attached. 6. Aborts and clears listeners when `close()` is called. `EventStatusStore` parses each message as `EventStatePayload`, updates its signals, and runs a one-second local timer. `HomeComponent` stops the store on destruction. # Key integration files | File | Responsibility | |---|---| | `frontend/src/app/app.routes.ts` | Registers shell and child routes. | | `frontend/src/app/core/interceptors/auth.interceptor.ts` | Adds Bearer authentication to Angular HTTP requests. | | `frontend/src/app/core/services/authenticated-event-source.service.ts` | Adds Bearer authentication to the browser SSE request, which does not use the Angular HTTP interceptor chain. | | `frontend/src/app/core/services/event-status.pure.ts` | Defines the event payload and transport interface. | | `tests/frontend/authenticated-event-source.spec.ts` | Regression coverage for authenticated SSE transport behavior. | # Event-status pure helpers `frontend/src/app/core/services/event-status.pure.ts` owns the small, no-Angular types and pure functions consumed by the event status pipeline. `EventStatusStore` re-exports them so application code can import from a single path. | Export | Purpose | |---|---| | `EventState` | Union `'running' \| 'countdown' \| 'stopped' \| 'unconfigured'`. | | `EventStatePayload` | Server-pushed event window payload shape. | | `EventSourceLike` | Minimal interface for any SSE transport the store can drive. | | `formatDdHhMm(seconds)` | Pure `DD:HH:mm` formatter. | | `deriveCountdownText(state, start, end)` | Pure mapping from event window state to countdown label. | | `LED_COLOR_BY_STATE` | `Readonly>` mapping each state to its theme CSS variable (`var(--color-success)`, `--color-warning`, `--color-danger`, `--color-secondary`). | | `ledBackgroundColor(state)` | Pure accessor returning the `background-color` value for the LED element. | `ShellHeaderComponent` exposes a `computed` signal `ledColor()` that calls `ledBackgroundColor(this.eventState())` and binds it to the LED via `[style.background-color]`. The component's `.led` base rule is therefore shape-only (size, radius, `inline-block`, vertical alignment); the visible color always comes from `LED_COLOR_BY_STATE` and is guaranteed to be a non-transparent theme token. The four `led-` classes remain on the element as selectors/test hooks but no longer own the color. # See also - [Authenticated Shell](/guides/authenticated-shell.md) - [Event Window](/guides/event-window.md) - [System Overview](/architecture/overview.md)