Jag bor i närheten av Hyllie station och pendlar regelbundet med tåg. Varje morgon samma rutin: öppna Skånetrafikens app, vänta på att den laddar, navigera förbi kampanjer och kartvy, för att till slut hitta avgångstiderna. Det fungerar, men det är mer friktion än nödvändigt för något man gör varje dag.

Lösningen var uppenbar: bygga något eget. Resultatet är hyllie.hakdah.com — en renodlad realtidsavgångstavla för Hyllie station, utan onödiga omvägar.
Varför inte bara använda befintliga lösningar?
Skånetrafikens app är bra för reseplanering, men överdimensionerad för det enkla användningsfallet ”vilket tåg går härnäst från min station”. Trafiklab har en webbtjänst, men den är inte optimerad för dagligt bruk på mobil. Avgångstavlor.se och liknande sajter är antingen reklamtunga eller långsamma.
Jag ville ha något som:
- Laddas omedelbart
- Visar exakt det jag behöver — linje, destination, spår, status
- Uppdateras automatiskt utan att jag behöver göra något
- Fungerar lika bra på mobilen som på desktop
ResRobot API:et — ryggraden i allt
All realtidsdata kommer från ResRobot, Trafiklab och Samtrafiken i Sveriges öppna API för kollektivtrafikdata. Det är gratis att använda med registrering och täcker i princip all kollektivtrafik i Sverige.
Endpoints jag använder
Sajten använder tre av ResRobots endpoints:
Departure Board — hämtar kommande avgångar från en given hållplats:
GET /v2.1/departureBoard?id=740001586&maxJourneys=20&format=json&accessId=…
Arrival Board — samma sak fast för ankomster:
GET /v2.1/arrivalBoard?id=740001586&maxJourneys=20&format=json&accessId=…
Trip — används när man klickar på en avgång för att se alla hållplatser längs rutten:
GET /v2.1/trip?originId=…&destId=…&date=…&time=…&passlist=true&format=json&accessId=…
Hyllie stations stop-ID i ResRobot är 740001586. Det hittar man via deras location.name-endpoint.
Svarsformatet
Varje avgång i svaret ser ut ungefär så här:
{ "date": "2026-03-08", "time": "08:14:00", "rtDate": "2026-03-08", "rtTime": "08:17:00", "direction": "Malmö Centralstation", "track": "2", "cancelled": false, "Product": [{ "name": "Pågatåget", "num": "1234", "catOut": "JRE" }]}
Fälten rtDate och rtTime är realtidstiderna — om de avviker från date/time är tåget försenat. Saknas de helt är tåget i tid. cancelled: true innebär inställt tåg.
Caching och API-kvot
ResRobot har en kvot på antal anrop per månad. För att hålla mig inom gränserna cachar sajten svaren i minnet och hämtar ny data max var 120:e sekund. Det räcker för att datan ska kännas levande utan att slösa på kvoten.
const REFRESH_MS = 120000;const cache = { departures: null, arrivals: null };const cacheTime = { departures: 0, arrivals: 0 };async function fetchDepartures() { const now = Date.now(); if (cache.departures && now - cacheTime.departures < REFRESH_MS) { return cache.departures; // Returnera cachad data } // Annars: hämta ny data från API:et const res = await fetch(`${RESROBOT_BASE}/departureBoard?id=${RESROBOT_STOP}&…`); const data = await res.json(); cache.departures = parseResRobot(data.Departure || [], 'departures'); cacheTime.departures = now; return cache.departures;}
Teknisk arkitektur — en enda HTML-fil
Hela sajten är en enda index.html utan ramverk, utan byggsystem, utan npm. Ren HTML, CSS och vanilla JavaScript. Det var ett medvetet val av flera skäl:
Laddningstid. Inga bundle-steg, ingen JavaScript som måste tolkas och kompileras av webbläsaren innan något syns. Sidan renderas direkt.
Underhåll. Det finns inget att uppdatera. Inga beroenden som blir inaktuella, inga säkerhetspatcher för npm-paket.
Portabilitet. Filen kan hoastas var som helst — en statisk webbserver, GitHub Pages, Cloudflare Pages — utan konfiguration.
Design och UX-val
Jag ville att designen skulle kännas som en riktig avgångstavla, inte en generisk webb-app. Det ledde till ett antal specifika beslut.
Mörkt tema med scanlines
Bakgrundsfärgen #0a0e14 — nästan svart med en blå underton — och ett subtilt scanlines-overlay via CSS ger känslan av en äldre monitertavla utan att vara kitschig. Scanlines-effekten är ett CSS repeating-linear-gradient med 4 pixelars upprepning och bara 7% opacitet, precis tillräckligt för att synas utan att störa läsbarheten.
body::before { content: ''; position: fixed; inset: 0; background: repeating-linear-gradient( 0deg, transparent, transparent 2px, rgba(0,0,0,0.07) 2px, rgba(0,0,0,0.07) 4px ); pointer-events: none; z-index: 1000;}
Typsnittsval
Två typsnitt med tydliga roller:
- Space Mono för alla siffror, tider, klocka och teknisk information. Monospace gör att siffror inte hoppar när de uppdateras, vilket är kritiskt för en avgångstavla.
- DM Sans för destinationsnamn och löptext. Lättläst sans-serif med modern karaktär.
För att minimera CLS (Cumulative Layout Shift) när fonterna laddas in används @font-face med size-adjust och ascent-override för att systemfallbacks ska ha så lika proportioner som möjligt mot de riktiga fonterna.
Färgkodning av status
Tre tillstånd, tre färger — enkla och intuitiva:
- Grön (
#3ddc84) — i tid, med pulserande punkt - Orange (
#ff9f45) — försenad, med antal minuter - Röd (
#ff5c5c) — inställd
Linjebrickor
Varje tågoperatör har sin egna färg på linjebrickan, hämtad från deras faktiska profilfarger:
const lineColors = { 'Pågatåget': { bg: '#e3001b', text: '#fff' }, 'Öresundståg': { bg: '#004b93', text: '#fff' }, 'Flygbussarna': { bg: '#ff6b00', text: '#fff' }, 'SJ': { bg: '#c8a200', text: '#000' },};
Popup med karta och hållplatslista
När man klickar på en avgång öppnas en popup med fullständig hållplatslista och en interaktiv karta via Leaflet.js med CartoDB Positron som kartlager — ljust, rent och utan API-nyckel. Rutten ritas ut som en gul linje med cirkelmarkörer för varje hållplats.
SEO och metadata
Eftersom sajten är statisk och inte indexeras av WordPress automatiskt lade jag extra vikt vid metadata i <head>:
- Fullständiga Open Graph-taggar för delning på sociala medier
- Twitter Card
- JSON-LD strukturerad data av typen
WebApplicationmedabout: TrainStation - Geografiska meta-taggar med koordinater för Hyllie station
- Canonical URL
Vad jag skulle göra annorlunda
Server-side rendering av första datahämtningen. Just nu gör sidan ett API-anrop direkt när den laddas, vilket ger en kort laddningsfläck. Med en liten server (t.ex. en Cloudflare Worker) hade man kunnat baka in aktuella avgångar direkt i HTML:en och eliminera det första nätverksanropet helt.
Service Worker för offline-stöd. En pendlare i tunneln hade uppskattat att se cachad data även utan uppkoppling.
PWA-manifest. Sajten fungerar bra som hemskärmsapp på mobilen, men ett komplett Web App Manifest hade gjort installationsupplevelsen bättre.
Sajten finns på hyllie.hakdah.com. Pendlar du från Hyllie? Bokmärk den, lägg till den på hemskärmen, eller skicka länken till någon som också väntar på Pågatåget.
Lämna en kommentar