How to map tfl-ts data into a useful London transport UI. The TypeScript files here are small, stack-agnostic references. They are not compiled by this package and do not pull in React, Next.js, or Tailwind.
See it working: API explorer — call the same endpoints this package wraps, with live responses.
Live React boards: tfl.manglekuo.com · source in ghcpuman902/tfl-components
Install a board into a Next.js app (copies source; installs tfl-ts from npm):
pnpm dlx shadcn@latest add https://tfl.manglekuo.com/r/tube-status-board.json| Mode | Identity | Helpers | Layout idea |
|---|---|---|---|
| Tube / rail (tube, Elizabeth, DLR, tram, Overground) | Official brand hex | getLineInlineStyles, getLineCssProps, severity helpers |
Sort → partition disruptions vs good service → colour title + horizontal bar |
| Bus | Route number chip | Do not use tube colour helpers | Discover stops → expand 490G… hubs if search returns them → poll boardable /^490\d/ IDs → arrivals row: [chip] [destination] [countdown] |
For a full React implementation, read tfl-components or poke the explorer. The mapping rules below work on any stack; React and Tailwind are optional.
| File | Purpose |
|---|---|
| node-cli.ts | Runnable Node CLI: search stop → arrivals (console) |
| caching.ts | Suggested TTLs for Next.js / server caches |
- Fetch once, then style. Call
line.getStatus/stopPoint.getArrivals, then apply helpers to the returned objects. - Disruptions first.
sortLinesBySeverityAndOrderthenisNormalServiceto split boards; denser cards for disruptions, compact grid for good service. ReadgetWorstCurrentStatus(line.lineStatuses), notlineStatuses[0]. Severity 20 is scheduled closure and sorts after incidents. Putting "not running" in its own section is a board choice. - Brand as CSS variables.
getLineCssProps(lineId)→--line-color, dark outline vars. Keep Northern black; outline for contrast (do not invert fill to white). - Bus ≠ tube. Route chips are generic; stop letter is a small badge; countdown is
Due/N minfromtimeToStation. Usestop.towards/stop.compassPointfromget/getByGeoPoint— not Predictionbearing. - Prefer boardable bus stops for arrivals. Boarding IDs match
/^490\d/(not/^490/—490G…are area hubs with no live arrivals). Name search: callclient.stopPoint.searchBusStops(query)so hubs are expanded.search({ modes: ['bus'] })is the raw TfL mix.