Configurable public-transport departure boards for Prague (PID), backed by the Golemio v2 API. Define a board once in PHP and it appears in the nav and renders live departures — no frontend changes required.
Stack: Symfony 5.4 (PHP ≥ 7.2.5) · Vue 3 + TypeScript · Webpack Encore (Less, Vue loader, ts-loader)
Renders one or more "boards" — each a set of stops with live departures pulled from Golemio. Time columns are enriched server-side with derived fields (timestamp, short label, minutes-from-now), and the frontend re-renders every second so past/current/future departures stay accurate without reloading.
The design deliberately keeps a single source of truth on the backend and treats the frontend as a thin, data-driven island.
- Twig is a thin shell. Every page renders
base.html.twig→ a single<div id="app" data-page="…">. Vue readsdata-pageinassets/main.ts, selects the matching page component, and passes remainingdata-*attributes as props. No rendering logic lives in Twig. - Boards are configuration, not code paths.
App\Service\BoardRegistryis the single source of truth for both the nav list and per-slug settings. Adding a board = one entry inBoardRegistry::BOARDS+ one case ingetBoardSettings(). No Vue changes needed. - Composable filters. Stop specs accept a
FilterInterface, a plain callable, or an array of them, applied in sequence (e.g.FilterByRouteNumber(['S3','R21']), destination-substring matches, etc.). - Strongly-typed API client.
PidApi::get()builds the request from the request object's route, produces a typed response, and hydrates each item. Items serialize to JSON with derived_ts/_short/_difftime fields for free.
- One Encore entry (
app);main.tsdispatches bydata-page— no per-page bundles. - No vue-router, no Pinia. The page component is the data root; shared state
flows via
provide/inject. - Components depend on an injected
BoardApi(the seam for tests/mocks), not onfetchdirectly. - Time comparisons use a shared 1 Hz clock (
useCurrentTime().nowSeconds) so rows tick in sync. - TypeScript runs in
strictmode.
- PHP ≥ 7.2.5, Composer
- Node.js + npm
- A Golemio API key
composer install # installs PHP + npm deps and builds assetsCreate .env.local with your key: