[
  {
    "slug": "skarmslackare-for-mac-och-windows",
    "title": "Skärmsläckare för Mac och Windows",
    "date": "2026-03-21",
    "image": "images/screensaver-hero.jpg",
    "summary": "SL Live Map finns nu som skärmsläckare för både macOS och Windows. Ladda ner, dubbelklicka, klart — kartan tar över skärmen efter några minuters inaktivitet.",
    "body": "<img src=\"/images/screensaver-hero.jpg\" alt=\"SL Live Map som skärmsläckare — Stockholms kollektivtrafik i realtid på en mörk karta i helskärm\" style=\"width:100%;border-radius:8px\">\n<p>Sedan lanseringen har flera personer frågat om man kan ha kartan igång på en skärm utan att behöva hålla en webbläsare öppen. Nu finns SL Live Map som skärmsläckare — för både macOS och Windows.</p>\n<h3>Så funkar det</h3>\n<p>Skärmsläckaren öppnar kartan i helskärm utan verktygsfält, menyrad eller muspekare. Du ser bara kartan med alla Stockholms fordon som rör sig i realtid. Inget att konfigurera — den laddar ner, installerar och aktiverar sig själv.</p>\n<p>Mac-versionen är ett installationspaket (.pkg) som lägger sig direkt i Systeminställningar. Windows-versionen är en liten installer (.exe, 587 KB) som sätter upp allt med ett dubbelklick. Om din dator saknar <span class=\"term\" data-def=\"WebView2 — Microsofts inbyggda webbläsarkomponent baserad på Chromium (samma motor som Edge). Förinstallerad på alla Windows 10/11-datorer sedan 2021 via Windows Update.\">WebView2</span> — vilket de flesta har sedan 2021 — erbjuder den att ladda ner det automatiskt.</p>\n<h3>Varför en skärmsläckare?</h3>\n<p>Jag ville ha kartan på en skärm i köket. En webbläsare i helskärm funkar, men den kräver att man håller den öppen manuellt. En skärmsläckare startar av sig själv efter några minuters inaktivitet och försvinner när man rör musen. Det kändes rätt.</p>\n<p>Skärmsläckaren uppdateras automatiskt — den laddar alltid den senaste versionen av kartan från nätet. Om servern uppdateras laddar den om sig själv, utan att du behöver göra något.</p>\n<h3>Ladda ner</h3>\n<p>Gå till <a href=\"/screensaver.html\">skärmsläckarsidan</a> och välj din plattform. Har du frågor eller problem med installationen? Hör gärna av dig via formuläret nedan.</p>"
  },
  {
    "slug": "batteri-fix-for-appen",
    "title": "🪫→🔋 Appen dränerar inte batteriet längre",
    "date": "2026-03-13",
    "summary": "En användare upptäckte att kartan fortsatte hämta data i bakgrunden efter att ha installerat den som app på iPhone. Tusentals onödiga anrop per dag — nu noll.",
    "body": "<h3>Problemet</h3>\n<p>Göran hörde av sig efter att ha installerat kartan som app på sin iPhone. Batteriet gick från fullt till halvt på en förmiddag. Han hade helt rätt — kartan fortsatte att hämta fordonspositioner varannan sekund, även när appen låg i bakgrunden eller telefonen var låst.</p>\n<p>Det innebar ungefär 43 000 anrop per dag som ingen hade nytta av. Varje anrop väcker telefonens nätverksradio, som sedan håller sig vaken i väntan på nästa — ett klassiskt mönster för batteridränering på mobiler.</p>\n<h3>Varför det hände</h3>\n<p>Kartan byggdes som en vanlig webbsida som man besöker i webbläsaren. När man stänger fliken eller navigerar bort försvinner sidan och all kod slutar köra — ingen batteripåverkan.</p>\n<p>Men när kartan installeras som <span class=\"term\" data-def=\"Progressive Web App — en webbsida som sparas som en app på hemskärmen. Den öppnas i helskärm och beter sig som en vanlig app, men körs fortfarande av webbläsarmotorn under huven.\">PWA</span> (app på hemskärmen) beter den sig annorlunda. iOS kan hålla appen vid liv i bakgrunden, och de tre datahämtningslooparna — fordonspositioner var 2:a sekund, besökarantal var 30:e sekund, versionskontroll var 60:e sekund — fortsatte snurra i tomma intet.</p>\n<h3>Lösningen</h3>\n<p>Kartan lyssnar nu på webbläsarens <span class=\"term\" data-def=\"Page Visibility API — ett webbläsar-API som meddelar när en sida blir synlig eller dold. Triggas när användaren byter app, låser telefonen eller minimerar fönstret.\">Page Visibility API</span>. Så fort appen inte syns på skärmen stoppas all datahämtning. När du öppnar appen igen startar allt omedelbart — du märker ingen skillnad, förutom att batteriet håller.</p>\n<p>Jag mätte med <span class=\"term\" data-def=\"Puppeteer — ett verktyg från Google för att fjärrstyra Chrome och mäta nätverkstrafik, laddtider och beteende automatiskt.\">Puppeteer</span> före och efter, med 30 sekunder synlig → 60 sekunder gömd → 30 sekunder synlig igen:</p>\n<table style=\"width:100%;border-collapse:collapse;font-size:0.88em;margin:1.2em 0\"><thead><tr><th style=\"padding:8px 10px;text-align:left;border-bottom:2px solid rgba(128,128,128,0.35)\"></th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Före 🪫</th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Efter 🔋</th></tr></thead><tbody><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">Anrop (60 s gömd)</td><td style=\"padding:7px 10px;text-align:right\">33</td><td style=\"padding:7px 10px;text-align:right\"><strong>0</strong></td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">Data (60 s gömd)</td><td style=\"padding:7px 10px;text-align:right\">1,2 MB</td><td style=\"padding:7px 10px;text-align:right\"><strong>0 B</strong></td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">Polling när synlig</td><td style=\"padding:7px 10px;text-align:right\">16 req/30 s</td><td style=\"padding:7px 10px;text-align:right\">16 req/30 s</td></tr></tbody></table>\n<p>Screensaver-läget (<code>?screensaver</code>) är undantaget — det är tänkt att köras kontinuerligt på en dedikerad skärm och pausar aldrig.</p>\n<p>Tack Göran för rapporten! Har du installerat kartan som app och märkt av batteriproblem bör det vara löst nu — appen uppdateras automatiskt nästa gång du öppnar den.</p>"
  },
  {
    "slug": "dar-ar-bat-80",
    "title": "Där är båt 80",
    "date": "2026-03-13",
    "image": "images/batar-linje80.webp",
    "summary": "Flera besökare har hört av sig och undrat varför pendelbåt linje 80 inte syns på kartan. Det visade sig att en föråldrad databas gjorde sex av sju båtar osynliga — nu är de tillbaka.",
    "body": "<img src=\"/images/batar-linje80.webp\" alt=\"Karta över Stockholms inlopp med elva båtprickar synliga — bland annat linje 80 mellan Nybroplan och Ropsten\" style=\"width:100%;border-radius:8px\">\n<h3>\"Var är båt 80?\"</h3>\n<p>Linje 80 är SL:s pendelbåt mellan Nybroplan och Ropsten, via Nacka strand, Kvarnholmen och Blockhusudden. Vissa turer fortsätter till Storholmen i Lidingö. Det är en av Stockholms mest trafikerade båtlinjer — och den saknades nästan helt på kartan.</p>\n<p>Flera besökare har hört av sig och undrat varför just den linjen inte syns. Jag grävde i datan och hittade orsaken.</p>\n<h3>Hur kartan kopplar ihop datan</h3>\n<p>Alla fordonspositioner kommer från Trafiklabs <span class=\"term\" data-def=\"General Transit Feed Specification Realtime — ett standardformat för realtidsdata om kollektivtrafik. Flödet innehåller alla fordon med position, hastighet och tidpunkt för senaste GPS-mätning.\">GTFS-RT</span>-flöde, som uppdateras varannan sekund. Varje fordon identifieras med ett tur-ID — ett unikt nummer för just den specifika turen (till exempel \"avgång 08:15 från Nybroplan mot Ropsten\").</p>\n<p>Men tur-ID:t i sig säger ingenting om vilken linje fordonet tillhör. För att veta att det är \"båt 80 mot Ropsten\" behöver vi slå upp tur-ID:t i en separat databas — <span class=\"term\" data-def=\"En förberäknad datastruktur som kopplar varje tur-ID till sin rutt, linje, trafikslag och destination. Kartans version innehåller över 100 000 poster.\">trip_lookup.json</span> — som kopplar varje tur till linje, trafikslag och destination. Fordon som inte hittas i databasen visas inte på kartan, eftersom vi inte vet vilken linje de tillhör.</p>\n<h3>Vad som hade hänt</h3>\n<p>Databasen byggdes den 17 februari, baserat på SL:s statiska GTFS-data. Sedan dess har SL uppdaterat sina underliggande data med nya tur-ID:n. Det innebar att de gamla ID:na för linje 80:s innerstadsturer (Nybroplan–Ropsten via Nacka) inte längre matchade.</p>\n<p>En av sju båtar — den som kör förlängningen till Storholmen — hade ett äldre tur-ID som fortfarande fanns kvar. Den syntes. De sex andra, som trafikerar den mest besökta sträckan, försvann.</p>\n<h3>Inte bara linje 80</h3>\n<p>Totalt var 32 fordon osynliga på grund av samma problem. Förutom linje 80 saknades bland annat:</p>\n<ul>\n<li>Båt <strong>80X</strong> (expressturer Nybroplan–Ropsten)</li>\n<li>Båt <strong>84</strong> (Strömkajen–Ålstäket via Riset)</li>\n<li>Båt <strong>2</strong> (Strömkajen–Gåshaga)</li>\n<li>Båt <strong>17</strong> (Stavsnäs–Nämdö)</li>\n<li>Flera busslinjer (163, 402, 444, 469, 687, 801, med flera)</li>\n</ul>\n<p>Efter uppdateringen gick matchningen från 97,2 % till 100 % — alla fordon som rapporterar position syns nu på kartan.</p>\n<h3>Framåt</h3>\n<p>För att förhindra att detta händer igen planerar jag att automatisera uppdateringen av trip_lookup.json, så att den hålls i synk med SL:s statiska data utan manuellt arbete.</p>\n<p>Tack till alla som hört av sig om detta — det hjälper verkligen. Ser du något annat som saknas eller ser konstigt ut? Hör gärna av dig via formuläret nedan.</p>"
  },
  {
    "slug": "38-procent-mindre-data",
    "title": "38 % mindre data med delta-uppdateringar",
    "date": "2026-03-06",
    "image": "images/delta-bandwidth.svg",
    "summary": "Ett mejl fick mig att ifrågasätta hur mycket data kartan egentligen skickar. Svaret: alldeles för mycket. Nu skickar servern bara det som ändrats sedan förra uppdateringen — och sparar över en megabyte per minut för varje besökare under rusningstid.",
    "body": "<img src=\"/images/delta-bandwidth.svg\" alt=\"Stapeldiagram som visar bandbreddsbesparingen: från 3 370 KB/min till 2 097 KB/min, en minskning med 38 procent\" style=\"width:100%;border-radius:8px;background:#1a1a2e;padding:12px\">\n<h3>Mejlet som startade allt</h3>\n<p>I förra veckan fick jag ett mejl från Teodor:</p>\n<blockquote>\"Blev lite intresserad av valet av överföring av datan till klienten. Det ser ut som klienten hämtar en komplett lägesbild av alla fordon från servern varje sekund. En väldig massa data som skickas. Nu kanske det är så att mycket av datan faktiskt ändras varje sekund?\"</blockquote>\n<p>Bra fråga. Jag visste att kartan pollade varje sekund, men hade aldrig mätt exakt hur mycket data det innebar. Dags att ta reda på det.</p>\n<h3>Hur mycket data är det egentligen?</h3>\n<p>Jag skrev ett mätscript med <span class=\"term\" data-def=\"Puppeteer — ett Node.js-bibliotek från Google för att fjärrstyra Chrome via DevTools Protocol. Kan mäta nätverkstrafik, ta screenshots och simulera riktiga användare.\">Puppeteer</span> som öppnar kartan och loggar all nätverkstrafik under en minut. Först mätte jag klockan tre på natten — 65 fordon ute, ~180 KB per minut. Inte så farligt.</p>\n<p>Men 80 % av kartans besökare sitter på mobilen, och de flesta tittar under dagen — morgonrusningen sammanfaller med flest besökare. Så jag mätte igen klockan åtta, med ~1 500 fordon i trafik:</p>\n<table style=\"width:100%;border-collapse:collapse;font-size:0.88em;margin:1.2em 0\"><thead><tr><th style=\"padding:8px 10px;text-align:left;border-bottom:2px solid rgba(128,128,128,0.35)\">Tid</th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Fordon</th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Per poll (<span class=\"term\" data-def=\"gzip — en komprimeringsalgoritm som webbservrar använder för att minska storleken på data innan den skickas till webbläsaren. Alla moderna webbläsare packar automatiskt upp gzip-komprimerad data.\">gzip</span>)</th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Per minut</th></tr></thead><tbody><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">03:00 (natt)</td><td style=\"padding:7px 10px;text-align:right\">65</td><td style=\"padding:7px 10px;text-align:right\">3 KB</td><td style=\"padding:7px 10px;text-align:right\">180 KB</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">08:00 (rusning)</td><td style=\"padding:7px 10px;text-align:right\">1 500+</td><td style=\"padding:7px 10px;text-align:right\">61 KB</td><td style=\"padding:7px 10px;text-align:right\"><strong>3,7 MB</strong></td></tr></tbody></table>\n<p>Nu ska det sägas att servern redan komprimerar all data med <span class=\"term\" data-def=\"gzip — en komprimeringsalgoritm som webbservrar använder för att minska storleken på data innan den skickas till webbläsaren. Alla moderna webbläsare packar automatiskt upp gzip-komprimerad data.\">gzip</span> innan den skickas. Den råa JSON-datan för 1 500 fordon är ungefär 500 KB, men gzip pressar ner den till ~60 KB. Det är alltså den komprimerade storleken som skickas — men med en poll varje sekund blir det ändå 3,7 MB per minut. Teodor hade rätt: det var en väldig massa data, även med komprimering.</p>\n<h3>Vad ändras egentligen?</h3>\n<p>Alla fordonspositioner kommer från <a href=\"https://www.trafiklab.se/\">Trafiklabs</a> <span class=\"term\" data-def=\"GTFS Realtime — ett öppet standardformat från Google för realtidsdata om kollektivtrafik. Innehåller fordonspositioner, hastighet, riktning och tidsstämplar. Läs mer på developers.google.com/transit/gtfs-realtime.\">GTFS-RT</span>-flöde, som SL:s operatörer matar med GPS-data. Varje fordon har 13 fält: id, position (lat/lon), <span class=\"term\" data-def=\"Bearing — kompassriktningen fordonet rör sig i, angett i grader. 0° = norr, 90° = öster, 180° = söder, 270° = väster.\">bearing</span>, speed, linje, <span class=\"term\" data-def=\"Headsign — texten som visas på fordonets destinationsskylt, till exempel 'Södersjukhuset' för buss 3.\">headsign</span>, transportmedel, med mera. Men de flesta fälten — linje, headsign, transportmedel, route_id — ändras <em>aldrig</em> under en tur. Det enda som rör sig är positionen och tidsstämpeln.</p>\n<p>Jag jämförde två på varandra följande <span class=\"term\" data-def=\"En ögonblicksbild (snapshot) av alla fordonspositioner vid en viss tidpunkt. Servern hämtar en ny snapshot från Trafiklab ungefär varannan sekund.\">snapshots</span> under rusningstid:</p>\n<table style=\"width:100%;border-collapse:collapse;font-size:0.88em;margin:1.2em 0\"><thead><tr><th style=\"padding:8px 10px;text-align:left;border-bottom:2px solid rgba(128,128,128,0.35)\">Fält</th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Andel som ändrades</th></tr></thead><tbody><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">timestamp</td><td style=\"padding:7px 10px;text-align:right\">79 %</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">lon</td><td style=\"padding:7px 10px;text-align:right\">62 %</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">lat</td><td style=\"padding:7px 10px;text-align:right\">58 %</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">speed</td><td style=\"padding:7px 10px;text-align:right\">45 %</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">bearing</td><td style=\"padding:7px 10px;text-align:right\">43 %</td></tr><tr style=\"border-top:2px solid rgba(128,128,128,0.35)\"><td style=\"padding:7px 10px\"><em>line, headsign, transport_mode, ...</em></td><td style=\"padding:7px 10px;text-align:right\"><em>0 %</em></td></tr></tbody></table>\n<p>Hälften av alla fält skickas om i onödan varje sekund utan att ha ändrats.</p>\n<h3>Lösningen: delta-uppdateringar</h3>\n<p>Konceptet är inspirerat av hur multiplayer-spel och appar som <a href=\"https://www.flightradar24.com/\">Flightradar24</a> hanterar realtidsdata — istället för att skicka hela världen varje frame, skickar man bara <span class=\"term\" data-def=\"Delta — skillnaden mellan två tillstånd. I nätverksprogrammering betyder det att bara skicka det som ändrats, inte allt. Ibland kallat 'diff' (efter Unix-kommandot diff).\">deltan</span>.</p>\n<p>Servern håller nu koll på de senaste ögonblicksbilderna. Klienten skickar med tidsstämpeln från sin senaste uppdatering, och servern svarar bara med:</p>\n<ul><li>Nya fordon som tillkommit (med alla fält)</li><li>Fordon som försvunnit (bara id:t)</li><li>Fordon som rört sig — men <strong>bara de fält som ändrats</strong></li></ul>\n<p>Första anropet ger fortfarande en komplett bild. Allt efter det är en liten diff. Mönstret liknar hur <a href=\"https://en.wikipedia.org/wiki/Operational_transformation\">operational transformation</a> fungerar i Google Docs — fast enklare, eftersom det bara finns en skrivare (servern).</p>\n<h3>Testresultat</h3>\n<p>Jag körde Puppeteer-mätningen i två minuter och jämförde gamla och nya versionen sida vid sida, mot samma realtidsdata under morgonrusningen:</p>\n<table style=\"width:100%;border-collapse:collapse;font-size:0.88em;margin:1.2em 0\"><thead><tr><th style=\"padding:8px 10px;text-align:left;border-bottom:2px solid rgba(128,128,128,0.35)\"></th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Före</th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Efter</th></tr></thead><tbody><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">Data per minut</td><td style=\"padding:7px 10px;text-align:right\">3 370 KB</td><td style=\"padding:7px 10px;text-align:right\"><strong>2 097 KB</strong></td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">Antal fordon (snitt)</td><td style=\"padding:7px 10px;text-align:right\">1 429</td><td style=\"padding:7px 10px;text-align:right\">1 429</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">Skillnad i fordon</td><td style=\"padding:7px 10px;text-align:right\" colspan=\"2\">0</td></tr></tbody></table>\n<p><strong>38 % mindre data, exakt samma karta.</strong> Det är ~1,3 MB per minut som varje mobilanvändare slipper ladda ner. Under en kvarts pendling sparar det ~20 MB — märkbart om man sitter på en begränsad <span class=\"term\" data-def=\"Mobildata — den datamängd du har i ditt mobilabonnemang. Många har 5–20 GB per månad, och streamade kartor kan äta upp det fort.\">mobildataplan</span>.</p>\n<h3>Bakåtkompatibelt och felsäkert</h3>\n<p>Om klienten inte skickar med en tidsstämpel, eller om servern inte har kvar den begärda ögonblicksbilden, faller systemet tillbaka till ett fullständigt svar — en teknik som ibland kallas <a href=\"https://en.wikipedia.org/wiki/Graceful_degradation\">graceful degradation</a>. Samma sak händer om något går fel — klienten nollställer sin lokala data och börjar om från en komplett bild. Ingen besökare märker skillnad, förutom att det går snabbare.</p>\n<p>Tack till Teodor för mejlet som satte igång det hela! Har du fler funderingar kring hur kartan funkar, eller idéer på förbättringar? Hör gärna av dig via formuläret nedan.</p>"
  },
  {
    "slug": "varfor-hoppar-sparvagnarna",
    "title": "Varför hoppar spårvagnarna?",
    "date": "2026-02-28",
    "summary": "En besökare undrade varför spårvagnarna rör sig ryckigare än bussarna. Jag kollade på rådata från Trafiklab — och hittade stora skillnader i hur ofta olika linjer faktiskt uppdateras.",
    "body": "<p>En besökare hörde av sig och undrade varför spårvagnarna på kartan verkar röra sig ryckigare än bussarna, som i jämförelse ser ut att glida på. Det är en bra observation — och svaret visar sig ligga i källdatan, inte i kartan.</p><h3>Hur jag undersökte det</h3><p>Kartan hämtar fordonspositioner från Trafiklabs <span class=\"term\" data-def=\"General Transit Feed Specification Realtime — ett standardformat för realtidsdata om kollektivtrafik. Flödet innehåller alla fordon med position, hastighet och tidpunkt för senaste GPS-mätning.\">GTFS-RT</span>-flöde ungefär varannan sekund. Varje fordon har ett <code>timestamp</code>-fält som anger när GPS-positionen senast uppdaterades hos källsystemet. Jag hämtade flödet vid två tillfällen med 30 sekunders mellanrum och jämförde: hur gamla är tidsstämplarna, och hur stor andel av fordonen fick ett nytt värde?</p><table style=\"width:100%;border-collapse:collapse;font-size:0.88em;margin:1.2em 0\"><thead><tr><th style=\"padding:8px 10px;text-align:left;border-bottom:2px solid rgba(128,128,128,0.35)\">Linje</th><th style=\"padding:8px 10px;text-align:left;border-bottom:2px solid rgba(128,128,128,0.35)\">Namn</th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Uppdaterade (30 s)</th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Snittålder</th><th style=\"padding:8px 10px;text-align:right;border-bottom:2px solid rgba(128,128,128,0.35)\">Värst</th></tr></thead><tbody><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">7</td><td style=\"padding:7px 10px\">Spårväg City</td><td style=\"padding:7px 10px;text-align:right\">80 %</td><td style=\"padding:7px 10px;text-align:right\">46 s</td><td style=\"padding:7px 10px;text-align:right\">219 s</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">21</td><td style=\"padding:7px 10px\">Lidingöbanan</td><td style=\"padding:7px 10px;text-align:right\">60 %</td><td style=\"padding:7px 10px;text-align:right\">2 min 10 s</td><td style=\"padding:7px 10px;text-align:right\">9 min 28 s</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">25–26</td><td style=\"padding:7px 10px\">Saltsjöbanan</td><td style=\"padding:7px 10px;text-align:right\">67 %</td><td style=\"padding:7px 10px;text-align:right\">1 min 37 s</td><td style=\"padding:7px 10px;text-align:right\">7 min 23 s</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">27–29</td><td style=\"padding:7px 10px\">Roslagsbanan</td><td style=\"padding:7px 10px;text-align:right\">87 %</td><td style=\"padding:7px 10px;text-align:right\">45 s</td><td style=\"padding:7px 10px;text-align:right\">6 min 11 s</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">30</td><td style=\"padding:7px 10px\">Tvärbanan (öst)</td><td style=\"padding:7px 10px;text-align:right\">86 %</td><td style=\"padding:7px 10px;text-align:right\">47 s</td><td style=\"padding:7px 10px;text-align:right\">5 min 14 s</td></tr><tr style=\"border-bottom:1px solid rgba(128,128,128,0.15)\"><td style=\"padding:7px 10px\">31</td><td style=\"padding:7px 10px\">Tvärbanan (väst)</td><td style=\"padding:7px 10px;text-align:right\">50 %</td><td style=\"padding:7px 10px;text-align:right\">4 min 24 s</td><td style=\"padding:7px 10px;text-align:right\">9 min 14 s</td></tr><tr style=\"border-top:2px solid rgba(128,128,128,0.35)\"><td style=\"padding:7px 10px\">—</td><td style=\"padding:7px 10px\"><em>Bussar (jämförelse)</em></td><td style=\"padding:7px 10px;text-align:right\"><em>91 %</em></td><td style=\"padding:7px 10px;text-align:right\"><em>30 s</em></td><td style=\"padding:7px 10px;text-align:right\"><em>—</em></td></tr></tbody></table><p>Kolumnen <em>Uppdaterade</em> visar andelen fordon som faktiskt fick ett nytt GPS-värde under mätfönstret. <em>Snittålder</em> är hur gamla tidsstämplarna i genomsnitt är när de dyker upp i flödet. <em>Värst</em> är det enskilda fordon som hade äldst data vid mätningstillfället.</p><h3>Problemet är i källan, inte på kartan</h3><p>Kortversionen: Trafiklab vidarebefordrar i princip rå data från respektive operatörs fordonssystem. Bussar uppdateras ungefär varannan sekund — det stämmer väl med att Nobina och andra bussoperatörer har moderna GPS-system. Spårvagnarna är en annan historia. Linje 31 (Tvärbanan väst, Liljeholmen–Alvik) hade i genomsnitt 4,5 minuters gammal GPS-data, och enstaka fordon dök upp med nästan tio minuters fördröjning.</p><p>Det innebär att kartan ibland visar ett fordon på en position det lämnade för länge sedan. Animationerna fyller ut gapen och gör det så smidigt som möjligt, men när källdatan hoppar från 9 minuter gammal till en ny position är hoppet oundvikligt.</p><h3>Riktning är alltid ett problem</h3><p>En sak gäller alla spårvagnar oavsett linje: <span class=\"term\" data-def=\"Kompassriktningen fordonet rör sig i, rapporterad av fordonets GPS. 0° = norr, 90° = öster och så vidare.\">bearing</span>-fältet i GTFS-RT rapporteras alltid som 0 för spårvagnar — de uppger helt enkelt ingen riktningsinformation. Kartan beräknar istället riktningen själv utifrån hur fordonet rör sig längs det kända spåret. Det fungerar bra när positionerna uppdateras tillräckligt ofta, men vid långa gap kan beräknad riktning bli fel tills nästa uppdatering landar.</p><p>Sett något konstigt, eller vill du rapportera en linje som beter sig märkligt? Hör gärna av dig via formuläret nedan.</p>"
  },
  {
    "slug": "spara-kartan-pa-hemskarmen",
    "title": "Spara kartan på hemskärmen",
    "date": "2026-02-27",
    "image": "images/pwa.jpg",
    "summary": "SL Live Map kan nu sparas som en app på hemskärmen — öppnas i helskärm utan adressfält. Plus en ny dela-knapp som använder telefonens inbyggda delning.",
    "body": "<img src=\"/images/pwa.jpg\" alt=\"SL Live Map-ikonen på en iPhone-hemskärm bredvid Telefon, Mail och Safari\" style=\"width:100%;border-radius:8px\"><p>Sedan starten har SL Live Map varit en webbsida du besöker i Safari eller Chrome. Det fungerar — men varje gång behöver du skriva in adressen eller hitta bokmärket. Nu kan du spara kartan som en app direkt på hemskärmen.</p><h3>Vad innebär det?</h3><p>När du lägger till kartan på hemskärmen blir den en <span class=\"term\" data-def=\"Progressive Web App — en webbsida som beter sig som en vanlig app. Den får en egen ikon, öppnas i helskärm och känns som en nedladdad app, men allt körs fortfarande i webbläsaren under huven.\">PWA</span> (Progressive Web App). Det betyder:</p><ul><li>En egen ikon på hemskärmen — precis som en vanlig app</li><li>Öppnas i <strong>helskärm</strong> utan Safaris adressfält och knappar</li><li>Eget fönster i appväxlaren</li></ul><p>Det är inte en app från App Store — det är samma webbsida som alltid, fast paketerad som en genväg som öppnas på ett snyggare sätt.</p><h3>Så gör du (iPhone)</h3><p>Det tar ungefär tio sekunder:</p><ol><li>Tryck på <strong>⋯</strong> (tre prickar) i Safaris verktygsfält</li><li>Tryck <strong>Dela</strong></li><li>Välj <strong>Lägg till på hemskärmen</strong></li><li>Se till att <em>Öppna som webbapp</em> är aktiverat och tryck <strong>Lägg till</strong></li></ol><p>Behöver du mer hjälp? Det finns en <a href=\"/install.html\">steg-för-steg-guide med bilder</a>.</p><h3>Enklare att dela</h3><p>Dela-knappen i kartan har också uppdaterats. På mobilen öppnar den nu telefonens inbyggda <span class=\"term\" data-def=\"Det systemfönster som dyker upp när du trycker Dela i vilken app som helst — med alternativ för SMS, AirDrop, Instagram, Messenger och alla andra appar du har installerade.\">dela-ark</span> så att du kan skicka kartan via SMS, AirDrop, Messenger eller vilken app du vill. På datorer kopieras länken till urklipp som förut.</p><p>I hamburgermenyn finns nu också en <strong>Dela</strong>-länk och en länk till <strong>Installera app</strong>-guiden.</p>"
  },
  {
    "slug": "ljust-lage-och-bussar-overallt",
    "title": "Ljust läge och bussar överallt",
    "date": "2026-02-27",
    "image": "images/ljust-lage-karta.webp",
    "summary": "Det mest efterfrågade önskemålet den senaste veckan har varit att kunna välja ett ljusare tema. Nu finns det — och bussarna syns i alla zoomlägen.",
    "body": "<img src=\"/images/ljust-lage-karta.webp\" alt=\"SL Live Map i ljust läge, utzoomad med bussar synliga över hela Stockholmsområdet\" style=\"width:100%;border-radius:8px\"><p>Sedan kartan gick live har det mest återkommande önskemålet varit: <em>\"Kan man inte få en ljus karta?\"</em> Det mörka temat är mysigt, men alla vill inte sitta i mörker mitt på dagen.</p><p>Nu finns ett ljust läge. Tryck på sol-ikonen i menyn så byter kartan till ljusa kartbilder, ljusa paneler och mörk text. Valet sparas och följer med mellan besök.</p><img src=\"/images/ljust-lage-meny.jpg\" alt=\"Närbild av hamburgarmenyn med alternativet Ljust läge markerat\" class=\"article-screenshot\"><h3>Hur det funkar</h3><p>Kartan använder <span class=\"term\" data-def=\"CSS Custom Properties — variabler som definieras en gång och återanvänds i hela stilmallen. Genom att byta en uppsättning variabler kan man ändra hela sidans utseende utan att röra enskilda regler.\">CSS-variabler</span> för alla färger i gränssnittet — toolbar, popups, knappar, statusfält. Ett klick byter ~35 variabler och laddar ljusa kartbilder från <span class=\"term\" data-def=\"Carto Positron — en ljus, minimalistisk kartstil som framhäver vägnätet utan att distrahera. Motsvarigheten till den mörka Dark Matter-stilen.\">CartoDB Positron</span> istället för Dark Matter.</p><p>Det mörka läget är fortfarande standard. Screensaver-läget (<code>?screensaver</code>) är alltid mörkt.</p><h3>Bussar i alla zoomlägen</h3><p>En annan sak folk har frågat om: bussarna försvann när man zoomade ut. Det var en medveten begränsning från början — tusen bussprickar på en utzoomad karta kunde vara överväldigande. Men folk ville se dem, så nu syns de oavsett zoomnivå. De visas som små prickar när man är utzoomad, och växer till fulla markörer med linjenummer när man zoomar in.</p>"
  },
  {
    "slug": "p4-stockholm-intervju",
    "title": "P4 Stockholm: \"Slow tv fast för webben\"",
    "date": "2026-02-25",
    "image": "images/p4-stockholm-artikel.jpg",
    "summary": "Sveriges Radio P4 Stockholm intervjuade Gunnar om SL Live Map — \"en stjärnhimmel med trafik dygnet runt\".",
    "body": "<img src=\"/images/p4-stockholm-artikel.jpg\" alt=\"Gunnar R Johansson intervjuas av P4 Stockholms reporter Farza utomhus i snön\" style=\"width:100%;border-radius:8px\"><p>P4 Stockholms reporter Farza träffade Gunnar för en intervju om SL Live Map och hobbyprogrammering.</p><p>Kartan beskrivs som \"lite Flight Radar för Stockholm\" — en realtidskarta där man kan följa bussar, tunnelbana, pendeltåg, spårvagnar och båtar. Idén föddes en kväll förra veckan efter att ha hittat öppen data på <a href=\"https://www.trafiklab.se/\">Trafiklab</a>.</p><blockquote>\"Det här är som slow tv fast för webben. Slow web. Man kan bara sitta och titta och tycka att det är vackert.\"</blockquote><p>Reaktionerna har varit överväldigande — folk skriver att de inte kan slita sig, och tåg­förare har hört av sig med glädje. Om motivationen:</p><blockquote>\"Det är lite som en kolonilott där man går och vattnar och funderar. Allting behöver inte bli någonting.\"</blockquote><p>Lyssna på intervjun:</p><audio controls preload=\"metadata\"><source src=\"/audio/p4-stockholm-2026-02-25.m4a\" type=\"audio/mp4\"></audio><p class=\"audio-caption\">Klipp från P4 Stockholm, Sveriges Radio, 25 februari 2026.</p>"
  },
  {
    "slug": "svd-kartan-visar-sl-trafiken-i-realtid",
    "title": "SvD: \"Gunnars karta visar SL-trafiken – i realtid\"",
    "date": "2026-02-25",
    "image": "images/svd-artikel.webp",
    "summary": "Svenska Dagbladet skriver om SL Live Map — \"Som mindfulness att titta på\".",
    "body": "<a href=\"https://www.svd.se/a/V69Wd6/kartan-visar-var-sl-trafiken-ar-i-realtid\"><img src=\"/images/svd-artikel.webp\" alt=\"Skärmdump från Svenska Dagbladets artikel om SL Live Map\" class=\"article-screenshot\"></a><p><a href=\"https://www.svd.se/a/V69Wd6/kartan-visar-var-sl-trafiken-ar-i-realtid\">Svenska Dagbladet</a> publicerade en artikel av reportern Maria Carling under rubriken <em>\"Gunnars karta visar SL-trafiken – i realtid\"</em>. Foto av Banfa Jawla.</p><p>Artikeln beskriver kartan som \"i högsta grad användbar — och en lisa för själen att titta på\" och lyfter fram reaktionerna från alla som hittat den:</p><blockquote>\"Bättre än tidtabellen ju.\"<br>\"Ser en prick för min buss på kartan, tittar upp och ser bussen åka förbi utanför fönstret!\"<br>\"Jag kan inte slita mig, vill bara sitta och titta på prickarna.\"</blockquote><p>Om motivationen bakom projektet:</p><blockquote>\"Att göra sånt här är min stickning eller kolonilott om du vill. Något jag går och petar i på lediga stunder.\"</blockquote><p><a href=\"https://www.svd.se/a/V69Wd6/kartan-visar-var-sl-trafiken-ar-i-realtid\">Läs hela artikeln på svd.se</a></p>"
  },
  {
    "slug": "battre-riktningsdetektering",
    "title": "Bättre riktningsdetektering i kurvor",
    "date": "2026-02-24",
    "summary": "Fordon som passerar skarpa kurvor i spårnätet hanteras nu korrekt — de fastnar inte längre i fel riktning.",
    "body": "<p>Ett fordon på röda linjen mot Ropsten rapporterades hoppa fram och tillbaka istället för att glida jämnt. Orsaken visade sig vara en grundläggande brist i hur kartan avgör vilken riktning ett fordon färdas.</p><h3>Problemet</h3><p>Varje spårbundet fordon har en <span class=\"term\" data-def=\"Kompassriktningen fordonet rör sig i, angett i grader (0° = norr, 90° = öster, 180° = söder, 270° = väster). Rapporteras av fordonets GPS.\">bearing</span> — en kompassriktning från GPS:en. Kartan jämför denna bearing med spårets riktning vid den aktuella positionen för att avgöra om fordonet åker \"framåt\" eller \"bakåt\" längs spåret.</p><p>Vid Ropsten gör tunnelbanespåret en skarp sväng där riktningen svänger från 30° (nordost) via 325° (nordväst) tillbaka till 58° (nordost). När ett fordon var mitt i kurvan kunde dess GPS-bearing peka i en helt annan riktning än det lokala spårsegmentet — och koden tolkade det som att fordonet åkte bakåt.</p><img src=\"/images/ropsten-kurva.svg\" alt=\"Schematisk bild av U-kurvan vid Ropsten där spårriktningen svänger från 30° via 325° till 58°\"><h3>Konsekvensen</h3><p>När riktningen sätts fel ignoreras alla framåtförflyttningar (de ser ut som \"bakåt\" ur kodens perspektiv). Fordonet står stilla. Efter ett antal ignorerade uppdateringar godkänns till sist en riktningsväxling — och fordonet hoppar fram hela den ackumulerade sträckan på en gång.</p><h3>16 kurvor i spårnätet</h3><p>En genomsökning av hela spårnätet hittade 16 platser med skarpa kurvor (>120° riktningsändring) som kunde utlösa samma problem:</p><ul><li><strong>T-Centralen</strong> — gröna linjens kurva under Gamla stan (linje 17, 18, 19)</li><li><strong>Tekniska högskolan</strong> — röda linjens sväng (linje 14)</li><li><strong>Rinkeby/Hallonbergen</strong> — blåa linjens kurva (linje 11)</li><li><strong>Ropsten</strong> — röda linjens terminalloop (linje 13)</li><li><strong>Alvik</strong> — Nockebybanan (linje 12)</li><li><strong>Gullmarsplan</strong> — Tvärbanan (linje 30)</li></ul><p>Dessutom påverkades flera pendeltåg (linje 40 och 48) av liknande problem.</p><h3>Lösningen</h3><p>Riktningsdetekteringen har nu en <span class=\"term\" data-def=\"Ett intervall där systemet säger &quot;jag vet inte&quot; istället för att gissa. Bättre att inte bestämma sig än att bestämma sig fel.\">dead zone</span>: om vinkeln mellan fordonets bearing och spårets riktning ligger mellan 45° och 135° klassas riktningen som tvetydig och fordonet antas åka framåt. Bara tydliga matchningar (<45°) eller tydliga motsatser (>135°) ger ett aktivt riktningsbeslut.</p><img src=\"/images/riktning-deadzone.svg\" alt=\"Diagram som visar dead zone mellan 45° och 135° där riktningen klassas som tvetydig\"><p>Gränsen för att godkänna en äkta riktningsväxling (som vid en ändhållplats) sänktes också från 5 till 3 på varandra följande bakåtuppdateringar — så att fordon vid terminus vänder snabbare.</p>"
  },
  {
    "slug": "snabbare-kartladdning",
    "title": "Snabbare kartladdning och ny meny",
    "date": "2026-02-24",
    "summary": "Kartan laddar nu betydligt snabbare tack vare lokalt hostad Leaflet, optimerad geodata och omstrukturerad laddningsordning. Dessutom en helt ny meny.",
    "body": "<p>Laddtiden för kartan har förbättrats rejält — <span class=\"term\" data-def=\"Tiden tills webbläsaren ritar det första synliga innehållet på skärmen. Ett standardmått från Google Lighthouse för att mäta hur snabbt en sida känns.\">First Contentful Paint</span> gick från 2,4 till 1,0 sekunder. Här är vad som ändrades.</p><h3>Leaflet flyttade hem</h3><p>Kartbiblioteket <a href=\"https://leafletjs.com\">Leaflet</a> laddades tidigare från <span class=\"term\" data-def=\"Ett populärt CDN (Content Delivery Network) som serverar npm-paket direkt. Snabbt för de flesta, men innebär en extra nätverksresa till en extern server.\">unpkg.com</span>, ett publikt CDN. Det innebar att webbläsaren först behövde göra en <span class=\"term\" data-def=\"Webbläsaren frågar en namnserver &quot;vilken IP-adress har unpkg.com?&quot; — det tar tid, särskilt första gången.\">DNS-uppslagning</span>, sedan <span class=\"term\" data-def=\"Krypteringsdansen som krävs för en säker HTTPS-anslutning: klient och server utbyter nycklar innan data kan skickas. Lägger till 1–2 nätverksrundturer.\">TLS-handskakning</span>, och till sist ladda ner filerna — allt innan kartan kunde börja renderas.</p><p>Nu servas Leaflets CSS och JavaScript direkt från samma server som resten av sidan. Det eliminerar hela den externa rundturen.</p><h3>Geodata på diet</h3><p>Spårsträckningarna för tunnelbana, pendeltåg och spårväg lagras som <span class=\"term\" data-def=\"Ett öppet filformat för geografisk data. Varje spårsträckning beskrivs som en lista av koordinater (longitud, latitud) som bildar en linje på kartan.\">GeoJSON</span>. Koordinaterna hade 14 decimalers precision — långt mer än vad som behövs. Sex decimaler (≈1 meters precision) räcker gott för en karta.</p><p>Resultatet: tunnelbanans spårfil krympte från 353 KB till 97 KB, en minskning på 72%. Totalt sparades flera hundra kilobyte nätverkstrafik.</p><h3>Stationerna fick en egen fil</h3><p>Drygt 240 stationer med namn och koordinater var tidigare hårdkodade direkt i HTML-filen och tog upp 62% av sidans storlek. Nu ligger de i en separat <span class=\"term\" data-def=\"JavaScript Object Notation — ett enkelt textformat för strukturerad data. Perfekt för listor av stationer med namn och koordinater.\">JSON-fil</span> som laddas asynkront. HTML-filen krympte från 74 KB till 61 KB, och stationerna laddas i bakgrunden utan att blockera kartan.</p><h3>Smartare laddningsordning</h3><p>Leaflets CSS laddas nu <span class=\"term\" data-def=\"Normalt väntar webbläsaren på att alla CSS-filer laddats innan den ritar något alls. Med en asynkron laddningsteknik kan sidan börja visas direkt medan stilmallen fortfarande laddas.\">icke-renderingsblockerande</span> — sidan börjar renderas direkt och kartans stilmallar appliceras när de är klara. De centrala kartrutorna <span class=\"term\" data-def=\"Webbläsaren får en tidig hint om att ladda resurserna parallellt med resten av sidan, istället för att vänta tills JavaScript-koden faktiskt begär dem.\">preloadas</span> också, så de finns i cache redan innan kartan skapas.</p><h3>Ny meny</h3><p>Den gamla titelraden och lagerpanelen har ersatts av en kompakt toolbar med <span class=\"term\" data-def=\"En designtrend där element ser ut som frostat glas — halvgenomskinlig bakgrund med en oskärpeeffekt (backdrop-filter: blur) som suddar ut innehållet bakom.\">glasmorfism</span>-design. På desktop syns lagerknapparna (T-bana, Pendeltåg, Spårväg, Båtar, Bussar) som klickbara chips direkt i verktygsfältet. På mobil finns en hamburgermeny.</p><p>I botten ligger en ny footer med fordonsräknare, antal besökare och senaste uppdateringstid.</p>"
  },
  {
    "slug": "morgonpasset-i-p3",
    "title": "Morgonpasset i P3 pratade om SL Live Map",
    "date": "2026-02-22",
    "image": "images/morgonpasset-artikel.png",
    "summary": "Branne och Matilda testade SL Live Map i direktsändning i Sveriges Radios Morgonpasset i P3.",
    "body": "<a href=\"https://www.sverigesradio.se/avsnitt/morgonpasset-i-p3-med-branne-pavlovic-och-matilda-range--4\"><img src=\"/images/morgonpasset-artikel.png\" alt=\"Skärmdump från Sveriges Radios sida om Morgonpasset i P3\" class=\"article-screenshot\"></a><p>Söndagen den 22 februari tog Morgonpasset i P3 upp SL Live Map. Programledarna Branne Pavlovic och Matilda Rånge pratade om kartan och det fina med att den finns.</p><p>Lyssna på inslaget:</p><audio controls preload=\"metadata\"><source src=\"/audio/morgonpasset-2026-02-22.m4a\" type=\"audio/mp4\"></audio><p class=\"audio-caption\">Klipp från Morgonpasset i P3, Sveriges Radio, 22 februari 2026.</p><p><a href=\"https://www.sverigesradio.se/avsnitt/morgonpasset-i-p3-med-branne-pavlovic-och-matilda-range--4\">Hela avsnittet på sverigesradio.se</a></p>"
  },
  {
    "slug": "linjar-animation",
    "title": "Linjär animation ger jämnare rörelser",
    "date": "2026-02-22",
    "summary": "Fordonsanimering byter från ease-out cubic till linjär interpolering, med 13% mer synlig rörelse och mjukare känsla.",
    "body": "<p>Alla fordon på kartan animeras mellan positionsuppdateringar för att ge en känsla av flyt. Tidigare användes en <span class=\"term\" data-def=\"En animeringskurva där rörelsen startar snabbt och saktar in mot slutet. Ger en naturlig &quot;landning&quot; men kan se konstigt ut vid upprepade korta animationer.\">ease-out cubic</span>-kurva: fordonen startade snabbt och bromsade in mot slutet av varje cykel. Det lät bra i teorin, men skapade ett problem.</p><img src=\"/images/easingkurvor.svg\" alt=\"Jämförelse av ease-out cubic och linjär easing — ease-out kryper de sista 50% av tiden\"><h3>Datadriven analys</h3><p>Genom att analysera 60 på varandra följande API-svar kunde jag mäta hur ofta varje fordonstyp uppdaterar sin position:</p><ul><li><strong>Bussar</strong> — var 2:a sekund, ~16 meters förflyttning</li><li><strong>Tunnelbana</strong> — var 6:e sekund, ~80 meters förflyttning</li><li><strong>Båtar</strong> — var 6:e sekund, ~12 meters förflyttning</li><li><strong>Pendeltåg</strong> — var 11:e sekund, ~650 meters förflyttning</li></ul><p>Med ease-out cubic tillbringade fordonen de sista 50% av varje animationscykel med att knappt röra sig — de såg ut att \"krypa\". Med 2 sekunders uppdateringsintervall betydde det en hel sekund av nästan-stillastående per cykel.</p><h3>Linjär interpolering</h3><p>Genom att byta till <span class=\"term\" data-def=\"Fordonet rör sig med exakt samma hastighet under hela animationen, utan acceleration eller inbromsning. Enklare matematik, jämnare resultat.\">linjär interpolering</span> rör sig fordonen med jämn hastighet under hela animationscykeln. Resultatet mätt med ett <span class=\"term\" data-def=\"Ett verktyg från Google som styr en riktig Chrome-webbläsare via kod. Jag använder det för att spåra fordonsmarkörer pixelvis och mäta animationskvalitet automatiskt.\">Puppeteer</span>-baserat testverktyg som spårar markörrörelser pixelvis:</p><ul><li>Synlig rörelse: 85% → <strong>97%</strong></li><li>\"Krypande\" tid: 15% → <strong>3%</strong></li><li>Jämnhet: +8 procentenheter bättre</li></ul><h3>Båtprediktion</h3><p>Båtar uppdaterar sin position bara var 6:e sekund, men kartan känner till deras hastighet och kurs. Genom att <span class=\"term\" data-def=\"Beräkna en framtida position baserat på nuvarande hastighet och riktning — &quot;om båten fortsätter rakt fram i 3 sekunder, var är den då?&quot;\">extrapolera</span> positionen 3 sekunder framåt fyller kartan gapet och båtarna glider naturligt även mellan uppdateringar.</p>"
  },
  {
    "slug": "snap-to-track",
    "title": "Fordon följer spåren",
    "date": "2026-02-22",
    "summary": "Tunnelbana, pendeltåg och spårväg snappar nu till sina spår istället för att glida fritt över kartan.",
    "body": "<p>Tunnelbanetåg, pendeltåg och spårvagnar rör sig nu längs sina faktiska linjesträckningar hämtade från <a href=\"https://www.openstreetmap.org/\">OpenStreetMap</a>. Tidigare rörde sig alla fordon i raka linjer mellan GPS-uppdateringar — det kunde se konstigt ut i kurvor och tunnlar.</p><h3>Hur det fungerar</h3><p>Spårsträckningarna lagras som <span class=\"term\" data-def=\"Ett öppet filformat för geografisk data. Varje spårsträckning beskrivs som en lista av koordinater (longitud, latitud) som bildar en linje på kartan.\">GeoJSON</span> med koordinater för varje linje. När en ny position kommer in söks den närmaste punkten på rätt spår — en teknik som kallas <span class=\"term\" data-def=\"&quot;Snäpp till spåret&quot; — istället för att visa fordonets råa GPS-position (som kan hamna bredvid spåret) projiceras den till närmaste punkt på den kända linjesträckningen.\">snap-to-track</span>. Sedan animeras fordonet längs spårets geometri till nästa position, vilket gör att det följer kurvor, växlar och tunnlar korrekt.</p><img src=\"/images/snap-to-track.svg\" alt=\"Illustration av snap-to-track: GPS-positioner projiceras till närmaste punkt på spåret\"><h3>Riktningsdetektering</h3><p>Varje fordon har en intern riktning (framåt eller bakåt längs spåret) som härleds från vilken riktning det rör sig. Riktningen är \"klibbig\" — det krävs fem på varandra följande baklänges-uppdateringar för att vända, vilket förhindrar flimmer vid stillastående eller vid stationer.</p><p>Sökningen efter närmaste spårpunkt är begränsad till ett fönster runt fordonets senaste kända position. Det hindrar fordon från att hoppa till parallella spår i närheten — särskilt viktigt där tunnelbanelinjer delar tunnel.</p>"
  },
  {
    "slug": "ny-teknik-folk-sitter-och-tittar",
    "title": "Ny Teknik: \"Folk sitter i timmar och tittar\"",
    "date": "2026-02-20",
    "image": "images/nyteknik-artikel.png",
    "summary": "Ny Teknik publicerar en artikel om SL Live Map — \"Hans sajt visar hur SL-trafiken rör sig\".",
    "body": "<a href=\"https://www.nyteknik.se/tech/hans-sajt-visar-hur-sl-trafiken-roer-sig-folk-sitter-i-timmar-och-tittar/4438565\"><img src=\"/images/nyteknik-artikel.png\" alt=\"Skärmdump från Ny Tekniks artikel om SL Live Map\" class=\"article-screenshot\"></a><p><a href=\"https://www.nyteknik.se/tech/hans-sajt-visar-hur-sl-trafiken-roer-sig-folk-sitter-i-timmar-och-tittar/4438565\">Ny Teknik</a> publicerade en artikel av reportern Kalle Wiklund under rubriken <em>\"Hans sajt visar hur SL-trafiken rör sig — folk sitter i timmar och tittar\"</em>.</p><p>Citatet i rubriken kommer från alla meddelanden som strömmat in sedan lanseringen:</p><blockquote>\"Det har kommit massor av kommentarer. Allting från personal som kör tågen som öser ut glädje, till andra som säger att de bara sitter i timmar och tittar.\"</blockquote><p><a href=\"https://www.nyteknik.se/tech/hans-sajt-visar-hur-sl-trafiken-roer-sig-folk-sitter-i-timmar-och-tittar/4438565\">Läs hela artikeln på nyteknik.se</a></p>"
  },
  {
    "slug": "destinationer-i-popupen",
    "title": "Destinationer i popupen",
    "date": "2026-02-20",
    "summary": "Klicka på ett fordon för att se vart det är på väg — \"Buss 3 mot Södersjukhuset\".",
    "body": "<p>Popupen som öppnas när man klickar på ett fordon visar nu slutdestination, till exempel <em>\"Buss 3 mot Södersjukhuset\"</em>. Det gör det mycket lättare att förstå vad man tittar på.</p><h3>Varifrån kommer informationen?</h3><p>Destinationerna kommer från <a href=\"https://www.trafiklab.se/\">Trafiklabs</a> <span class=\"term\" data-def=\"General Transit Feed Specification — ett internationellt standardformat för kollektivtrafikdata, skapat av Google. Används av hundratals trafikbolag världen över för att beskriva linjer, hållplatser, tidtabeller och realtidspositioner.\">GTFS</span> Sweden 3 Static-dataset. Det innehåller över 95 000 unika tur-ID:n som varje fordon rapporterar i realtid.</p><p>Vid serverstart byggs en <span class=\"term\" data-def=\"En förberäknad datastruktur som kopplar varje tur-ID till sin rutt, linje, trafikslag och destination — ungefär som ett register bak i en bok, fast med 95 000 poster.\">uppslagstabell</span> som kopplar varje tur-ID till rutt, linjenummer, trafikslag och destination. Tabellen är komprimerad till 3,4 MB genom att deduplicera strängar — varje unikt linje- och destinationsnamn lagras bara en gång.</p>"
  },
  {
    "slug": "feber-harmonisk-livekarta",
    "title": "Feber: \"Harmonisk livekarta\"",
    "date": "2026-02-18",
    "image": "images/feber-artikel.webp",
    "summary": "Teknikbloggen Feber skriver om kartan — \"en otroligt harmonisk karta över Stockholm\".",
    "body": "<a href=\"https://feber.se/internet/harmonisk-livekarta-over-alla-bussar-och-tag-/488597/\"><img src=\"/images/feber-artikel.webp\" alt=\"Skärmdump från Febers artikel om SL Live Map\" class=\"article-screenshot\"></a><p>Teknikbloggen <a href=\"https://feber.se\">Feber</a> uppmärksammade SL Live Map under rubriken <em>\"Harmonisk livekarta över alla bussar och tåg\"</em>. Artikeln publicerades av Roger Åberg.</p><p>Feber, som tidigare skrivit om <a href=\"https://biljettkoll.se\">Biljettkoll</a>, beskriver kartan som \"en otroligt harmonisk karta över Stockholm\" och noterar att det vid skrivande stund rullade omkring 1 700 fordon i SL:s regi.</p><p><a href=\"https://feber.se/internet/harmonisk-livekarta-over-alla-bussar-och-tag-/488597/\">Läs hela artikeln på feber.se</a></p>"
  },
  {
    "slug": "tunnelbana-till-dalaro",
    "title": "\"Tunnelbana 19 mot Dalarö\"",
    "date": "2026-02-18",
    "image": "images/tunnelbana-dalaro.jpg",
    "summary": "En uppmärksam pendlare upptäckte att Waxholmsbolagets båtar visades som tunnelbanetåg — mitt ute i skärgården.",
    "body": "<p>Johnny som jobbar på pendeln och bor i Haninge uppmärksammade på Facebook att det var sällsynt med tunnelbana till Dalarö. Han hade rätt — det var en bugg.</p><img src=\"/images/tunnelbana-dalaro.jpg\" alt=\"Skärmdump som visar popupen 'Tunnelbana 19 mot Dalarö' ute i skärgården\"><p class=\"img-caption\">\"Tunnelbana 19 mot Dalarö\" — en Waxholmsbåt förvirrad av delade linjenummer.</p><h3>Problemet</h3><p>Waxholmsbolagets båtlinjer delar nummer med tunnelbanan: linje 10, 11, 13, 14, 17 och 19 finns hos båda. Kartans fordonsdata kommer från <span class=\"term\" data-def=\"General Transit Feed Specification — ett internationellt standardformat för kollektivtrafikdata. Varje fordon rapporterar sitt tur-ID, och servern slår upp trafikslag via en uppslagstabell.\">GTFS</span> och varje fordon identifieras via sitt tur-ID som kopplas till en rutt och ett trafikslag.</p><p>Den första fixen var enkel men för bred: alla fordon med kända tunnelbanenummer klassades som tunnelbana, oavsett vad GTFS-datan sa. Det löste det ursprungliga problemet (tunnelbanelinjer som felaktigt visades som båtar) men skapade motsatt bugg — <em>Waxholmsbåtarna blev tunnelbanetåg</em>.</p><h3>Lösningen</h3><p>Fixen var en extra kontroll: om <span class=\"term\" data-def=\"GTFS route_type — en sifferkod som anger trafikslag. 401 = tunnelbana, 1000 = båt, 700 = buss osv. Varje tur i GTFS-datan har en route_type som anger vilken typ av fordon det är.\">GTFS-typen</span> säger att fordonet är en båt, får det vara en båt — oavsett linjenummer. Bara fordon som <em>inte</em> redan är klassade som båt kan övergå till tunnelbana via linjenummer.</p><p>Tack Johnny för att du hörde av dig — gör gärna som Johnny och rapportera om du ser något som ser konstigt ut!</p>"
  },
  {
    "slug": "lansering",
    "title": "SL Live Map lanseras",
    "date": "2026-02-17",
    "summary": "Kartan är live med bussar, tunnelbana, pendeltåg, spårväg och båtar i realtid.",
    "body": "<p>Första versionen av SL Live Map är publicerad. Kartan visar alla SL-fordon som rapporterar GPS-position via <a href=\"https://www.trafiklab.se/\">Trafiklabs</a> <span class=\"term\" data-def=\"Realtidsdelen av GTFS-standarden. Fordon skickar sin GPS-position, hastighet och riktning till ett centralt flöde som uppdateras varannan sekund.\">GTFS Realtime</span>-flöde.</p><p>Under rusningstid syns runt tusen fordon samtidigt. Varje fordon visas som en färgad prick med linjenummer — röda och blåa bussar, gröna/röda/blåa tunnelbanetåg, lila pendeltåg, blå spårvagnar och turkosa båtar.</p><p>Kartan är byggd med <a href=\"https://leafletjs.com\">Leaflet</a> och mörka kartplattor från <a href=\"https://carto.com\">CARTO</a>. Positionerna uppdateras varje sekund och fordonen animeras smidigt mellan uppdateringarna med <span class=\"term\" data-def=\"Ett webbläsar-API som kör animationer synkroniserat med skärmens uppdateringsfrekvens (vanligtvis 60 fps). Ger mjukare rörelser och bättre batteritid än t.ex. setInterval.\">requestAnimationFrame</span>.</p>"
  }
]
