Regular browser users were served a CSR shell (empty <app-root>) instead of server-rendered content. The browser painted a blank page, then waited for Angular to bootstrap and lazy-load the route — causing a visible blank-to-content flash.
Fix
All requests now route through the Angular SSR engine (appEngine.handle()). The SSR engine already fetches fresh station config from the API via APP_INITIALIZER before rendering, so the first paint carries real content, colors, and assets.
Changes
server.ts: Removed spider-only SSR gate. Removed unused isSpider/getUserAgent imports. Kept serveCsrShell as dead code for now (future fallback).
server.spec.ts: Updated tests to verify no spider gate exists and SSR engine is used for all requests.
Why this works
The SSR engine (main.server.ts) already blocks rendering until stationConfig.load() resolves. This means every request — spider or human — gets HTML with real DB data. The cost concern that motivated spider-only SSR is moot: SSR is fast enough for the site traffic.
## Problem
Regular browser users were served a CSR shell (empty `<app-root>`) instead of server-rendered content. The browser painted a blank page, then waited for Angular to bootstrap and lazy-load the route — causing a visible blank-to-content flash.
## Fix
All requests now route through the Angular SSR engine (`appEngine.handle()`). The SSR engine already fetches fresh station config from the API via `APP_INITIALIZER` before rendering, so the first paint carries real content, colors, and assets.
## Changes
- **server.ts:** Removed spider-only SSR gate. Removed unused `isSpider`/`getUserAgent` imports. Kept `serveCsrShell` as dead code for now (future fallback).
- **server.spec.ts:** Updated tests to verify no spider gate exists and SSR engine is used for all requests.
## Why this works
The SSR engine (main.server.ts) already blocks rendering until `stationConfig.load()` resolves. This means every request — spider or human — gets HTML with real DB data. The cost concern that motivated spider-only SSR is moot: SSR is fast enough for the site traffic.
The CSR shell served to regular browsers caused a visible blank-to-content
flash: the browser painted an empty <app-root>, then waited for Angular
to bootstrap and lazy-load the route before any content appeared.
All requests now route through the Angular SSR engine (appEngine.handle()),
which fetches fresh station config from the API via APP_INITIALIZER before
rendering. The first paint carries real content, colors, and assets.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
Regular browser users were served a CSR shell (empty
<app-root>) instead of server-rendered content. The browser painted a blank page, then waited for Angular to bootstrap and lazy-load the route — causing a visible blank-to-content flash.Fix
All requests now route through the Angular SSR engine (
appEngine.handle()). The SSR engine already fetches fresh station config from the API viaAPP_INITIALIZERbefore rendering, so the first paint carries real content, colors, and assets.Changes
isSpider/getUserAgentimports. KeptserveCsrShellas dead code for now (future fallback).Why this works
The SSR engine (main.server.ts) already blocks rendering until
stationConfig.load()resolves. This means every request — spider or human — gets HTML with real DB data. The cost concern that motivated spider-only SSR is moot: SSR is fast enough for the site traffic.Pull request closed