Changes.
This site is our own weekend project, and this is its logbook: everything that changed, day by day, baked in when the site was built. The link in the footer says when that was.
- Hjältebilden i inläggskorten på Anteckningsboken. Färgfältet överst i varje kort på
/anteckningsbok(och/en/anteckningsbok) är nu inläggets hjältebild, beskuren till samma höjd; kategorietiketten ligger kvar ovanpå bilden och de dekorativa formerna försvinner när det finns en bild. Det utvalda inlägget visar på samma sätt hjältebilden i hela vänsterhalvan, med ”NYTT”-tejpen kvar och den stora roterade kategorin borttagen. Inlägg utan hjältebild behåller färgfältet. Bilderna hämtas i flera bredder medsrcsetoch nyasizes(IMG_SIZES.postCard,IMG_SIZES.featuredCard), korten under vecket laddas lat, och bilderna har tom alt-text eftersom kortets rubrik redan är länktexten. Listfrågan hämtade redanheroImage, så ingen ändring i Sanity. Kontrollerat: prerendern ger bild i alla 17 kort och det utvalda, skärmbilder i headless Chrome på 1 280 och 390 px utan horisontell överskjutning. ESLint: samma kändaset-state-in-effect-fel iBlogPage.jsxföre och efter.
- Bildgalleri på blogginlägg, placerat i brödtexten med
. Ett inlägg har nu fältetimages[]i Studio (bild medhandle, alt-text och bildtext; handle är gemener, siffror och bindestreck). Ett stycke i brödtexten som bara innehållerrenderas som en figur med samma ram som hjältebilden — kantlinje, förskjuten skugga och bildtext under — viatransformBody(body, { images })ifrontend/src/lib/portableText.jsxoch den nyaFigure.jsx; alt-texten i stycket vinner över galleriets när den anges,srcsetochsizesföljer hjältebilden, och bredd/höjd sätts från Sanitys bildmetadata så layouten inte hoppar när bilden laddas. Ett okänt handle visar en streckad ”Missing image”-ruta i dev-bygget och ingenting i produktion; en referens mitt i ett stycke lämnas som text. Meta-beskrivning, RSS-flöde och sökindex rensar bort referenserna. Sanity-frågan för enskilt inlägg projicerar galleriet med URL och mått. Studio och schema deployade samma dag; befintliga inlägg påverkas inte. - Ny bloggpost publicerad: "Ett besök på Tokyo Game Show 2026" (
/anteckningsbok/tokyo-game-show-2026, kategori Bolaget, 4 min). Reseberättelse från konferensresan med Geeks AB till mässans 30-årsjubileum på Makuhari Messe — branschdagen den 17 september, skalan (elva hallar, 1 138 utställare från 53 länder), indieområdet, merchandise och tyfonen som ställde in sista mässdagen — med länkar till mässans officiella pressmeddelanden och en utgående länk till geeks.se. Första inlägget som använder galleriet: tretton foton från mässan placerade intill de stycken de illustrerar, samtliga med svensk alt-text och bildtext; hjältebilden är en genererad isometrisk illustration av Makuhari Messes entré i sajtens stil. Fotona skalades till max 2 400 px och rensades på EXIF och GPS-position innan uppladdning, som gick viasanity exec --with-user-tokeneftersom läs-token i.envinte får skapa assets.
- Vår leverans: sajtens egna DORA-mätvärden (
/var-leverans+/en/var-leverans, länkad i sidfoten efter deploy-stämpeln — ”Senast deployad … · Vår leverans →” — och i llms.txt). Fyra rutor — deployfrekvens per vecka, ledtid för ändringar (median, med 90-percentil i noten), andel misslyckade ändringar och återställningstid — följt av ett stapeldiagram över driftsättningar per svensk kalendervecka (kodändringar i bläck, innehållsombyggen i grått, pågående vecka i orange; hover/fokus per vecka ger siffrorna, tabellerna nedanför bär samma tal), de tio senaste driftsättningarna med ledtid, ev. misslyckade ändringar, ”Så räknar vi” och en ärlig begränsning: sajten saknar övervakning, så ett fel ingen återställde räknas inte. Källan är GitHubs deployment- och commit-API för repot, lästa iprebuildavscripts/generate-delivery.jstillpublic/leverans.json(gitignorerad): Vercels integration registrerar ett GitHub Deployment per produktionsbygge och ettsuccess-status varje gång en version går live — första gången för pushen, sedan för varje ombygge från Sanity-webhooken — så varjesuccessär en driftsättning med tidsstämpel; ledtiden räknas från commitens författardatum (för squash-mergade PR:ar från branchens första commit) till första driftsättningen som innehöll den; misslyckade ändringar ärfailure/error-status eller commits som senare revertats på main. Fönster: tretton kalenderveckor. Vid bygget 2026-09-10: 132 driftsättningar (82 kod, 50 ombyggen) på 88 dagar, 10,5 per vecka, ledtid median 1 min och 90 % inom 4 min över 89 commits, 0 misslyckade. Utan token (GITHUB_TOKEN, annarsgh auth tokenlokalt) eller vid API-fel skrivsavailable: falseoch sidan säger att talen inte kunde räknas — bygget stannar aldrig på sajtens egna mätvärden. Kräver en read-onlyGITHUB_TOKENsom miljövariabel i Vercel-projektet paperphyte innan sidan visar siffror live. Sidan prerendras på båda språken med JSON:en i seeden (861 ord), ligger i sitemapen, nyuseDelivery-krok ilib/buildInfo.jsbredvid changeloggen. Kontrollerat i headless Chrome: hover på vecka 31 aug ger ”48 kodändringar, 38 ombyggen” och talet 86 över stapeln, tabb landar på sidan utan fel, ingen horisontell överskjutning på 390 px. ESLint 24 fel före och efter. - Mini-Väntetidskalkylator på startsidan. Överst i verktygssektionen, före de fyra korten: de tre reglagen som bär resonemanget (utvecklare, byggen per dag, minuter per bygge) och de två siffrorna de ger — förlorade utvecklartimmar och kronor per år — som räknas om medan man drar. Andelen förlorad väntan och timkostnaden ligger kvar på verktygets standard (60 %, 850 kr) och nämns i en fotnot; ”Räkna vidare →” öppnar hela kalkylatorn med samma siffror i adressen (
?dev=&b=&min=), så inget behöver dras om. Konstanterna och matematiken är utbrutna ur sidan tillsrc/lib/vantetid.js(LIMITS,DEFAULTS,computeWait,inputsFromSearch,searchFromInputs) och används av både verktyget och widgeten, så de kan aldrig visa olika tal; kalkylatorsidan beter sig som förut. Två kolumner från 761 px (reglage till vänster, resultat till höger bakom en linje), staplat på mobil. Kontrollerat i headless Chrome mot bygget: standardvärdena ger 1 056 timmar och 897 600 kr (samma som lanseringsinlägget), 25/6/8 ger 2 640 timmar och 2 244 000 kr i widgeten och exakt samma i verktyget efter klick på länken, engelska startsidan formaterar ”1,056” / ”SEK 897,600” och länkar under/en. Inga sidfel; ESLint 24 fel före och efter. Ur TODO:ns ”Startsidan: visa sådant som händer på andra ställen”. - Sök på sajten (
/sok+/en/sok, förstoringsglas i sidhuvudet bredvid språkväxlaren, med etikett i mobilmenyn). Ett fält, resultat i tre grupper — Verktyg, Ordlista, Inlägg — med rubrik, metarad (kategori och datum för inlägg, ”9 frågor · 5 minuter” för verktyg) och ett utdrag runt första träffen i brödtexten, träfforden markerade. Index:scripts/generate-search-index.jskörs iprebuildbredvid sitemap och RSS och skriverpublic/search-index.json— inläggens rubrik, ingress, taggar och hela brödtexten som ren text (kodblock bortplockade), ordlistans term och kortdefinition på båda språken, verktygens namn, ingress och punkter ur i18n på båda språken; 70 poster, 93 kB (32 kB gzippat), gitignorerad som feeden. Sökningen (src/lib/search.js) sker i webbläsaren: indexet hämtas först vid första tangenttrycket (eller direkt vid?q=), aldrig annars; varje ord i frågan måste träffa någonstans; träff i rubrik väger tyngst, sedan taggar/term, ingress och brödtext, med ordgränsbonus; diakritiska tecken viks så att ”vantetid” hittar Väntetidskalkylatorn; högst tolv per grupp. Frågan ligger i?q=(ersätter historikposten per tangenttryck, så bakåtknappen inte stegar genom bokstäverna) och kan delas. På/envisas termer och verktyg på engelska och inläggen — som är svenska — med markeringen ”in Swedish” viaPostLink. Sidan ärnoindex, followoch ligger utanför sitemapen men prerendras (tom) på båda språken så att adressen svarar 200 hos Vercel. Kontrollerat i headless Chrome mot bygget: inga indexanrop före första tangenttrycket, ett efter; ”golden path” ger termen och tre inlägg, ”vantetid” verktyget och tre inlägg, ”error budget” på engelska två termer under/en/ordlista/…, ”xyzzy” tomläget; historiklängden växer inte med skrivandet. ESLint: 24 fel före och efter. Notering: inlägg medpublishedAti framtiden (Backstage-inlägget är just nu daterat 2026-09-11) kommer med i indexet först vid nästa bygge efter den tidpunkten, som för RSS och sitemap. - Ordlistelänkar på tjänstesidor och uppdrag. Samma automatiska länkning som inläggen har haft sedan ordlistan kom: första omnämnandet av en term i brödtexten blir en prickad länk till
/ordlista/<slug>med kortdefinitionen som tooltip. Tjänstesidornas intro och alla sektioner samt uppdragens beskrivning går nu genomlinkGlossaryTerms(eftertransformBody, som förut). Nyseen-mängd i länkaren så att en term länkas en gång per *sida*, inte en gång per sektion — Plattformsteknik-sidan länkar tio termer på svenska och elva på engelska, DevOps sex, Delivery Engineering fyra, DX fem (sex på engelska, där ”developer portals” träffar Utvecklarportal; den svenska texten säger också ”developer portals” och träffar därför inte den svenska termen).useGlossaryTermsläser nu ordlistan ur prerenderns seed och hämtar viafetchSanity, så listan (23 termer, 14 kB JSON) följer med i varje prerendrad sida som länkar och länkarna finns vid första målningen i stället för att försvinna vid hydreringen och komma tillbaka efter hämtningen — det gällde även inläggen tidigare. Fallstudiernas layout (ATG, QRGeno, DeLaval, Urb-it) renderar egna strängfält och får varken länkar eller seed; kroken tar ettenabled-argument och uppdragssidan slår på den först när dokumentet är laddat och inte är en fallstudie. Inget av de sjutton vanliga uppdragen nämner i dag någon term, så där syns ingen skillnad ännu. Kontrollerat: länkaren körd över alla tjänstesidor och uppdrag på båda språken utan dubbletter; prerender av Plattformsteknik, DevOps, Delivery Engineering, Euroflorist och DeLaval; hydrering i headless Chrome med ordlistehämtningen blockerad behåller alla länkar (10/10 sv, 11/11 en,/en/ordlista/…med engelsk tooltip). ESLint: 24 fel före och efter (de kändaset-state-in-effect).
- Ny bloggpost publicerad: "Backstage är inte plattformen — det är dörren till den" (
/anteckningsbok/backstage-ar-inte-plattformen, kategori DX, 5 min). Tesen: en utvecklarportal är dörren till den interna utvecklarplattformen, inte plattformen — katalogen svarar på vad som finns, dokumentationen på hur det fungerar och mallarna på hur man gör, och bara mallen utför något. Fyra sätt portaler dör (katalogen som ruttnar, wiki med bättre tema, mallen ingen underhåller, fel mått), ett avsnitt om varför repot ska äga det portalen visar så att människor och kodagenter får samma svar, och fem steg som börjar utan Backstage. Länkar till golden paths-, plattform som produkt- och agent-inläggen samt IDP-termen. Genererad hero-bild i sajtens isometriska stil med svensk alt-text. - Ny ordlisteterm: Utvecklarportal (Backstage) (
/ordlista/utvecklarportal, sv + en), samma form som de 22 befintliga. Termen låg på gränsen enligt regeln ”bara sådant sajten redan säger” — tolv omnämnanden på DX-tjänstesidan men inget inlägg — och publicerades tillsammans med inlägget ovan, som använder den; auto-länkaren träffar termen på första ”Backstage”. Relaterade tjänster Developer Experience och Plattformsteknik; relaterade termer IDP, Golden path, DX och Platform engineering, med spegelreferenser tillbaka i alla fyra. Kontrollerat: brödtexterna renderar genom Portable Text-pipelinen utan kvarvarande markdown, definitionerna är 250/252 tecken, alla referenser löser upp åt båda hållen. Ordlistan har 23 termer. Notering: bildgeneratorn publicerade inlägget av sig själv när bilden laddades upp; det avpublicerades inom några minuter och publicerades sedan avsiktligt med termen. - Ny bloggpost publicerad: "Bygg en gång: det ni testade ska vara det ni driftsätter" (
/anteckningsbok/bygg-en-gang, kategori Delivery Engineering, 5 min). Tesen: en pipeline som bygger om inför produktion driftsätter något som aldrig testats, eftersom ett bygge är en funktion av koden och allt annat som råkar vara sant i ögonblicket — basimage på ”latest”, verktygskedjan på runnern, det som hämtas från nätet under bygget och miljövariabler vid byggtid. Principen bygg en gång, befordra artefakten: en oföränderlig artefakt med digest eller checksumma går genom test, staging och produktion, och miljöerna skiljer sig i konfiguration vid körning. Fyra vanliga fällor (frontend-bygget som bakar in API-adressen, taggar som skrivs över, den separata produktionspipelinen, tron att lockfilen räcker) och fem steg för att börja. Länkar till ordlistans CI/CD, Feature flags och Progressive delivery samt tjänstesidan Delivery Engineering. Första inlägget med kategorietiketten Delivery Engineering. Genererad hero-bild i sajtens isometriska stil med svensk alt-text; brödtexten kontrollerad genomtransformBodyutan kvarvarande markdown.
- Sex nya ordlistetermer, valda efter vad sajten redan säger. Alla 70 innehållssidor (inlägg, tjänstesidor, branschintron, uppdrag, verktygstexterna, llms.txt och ordlistan själv) genomsökta efter ett åttiotal kandidattermer inom leveransteknik, DX, plattform, SRE och AI-assisterad utveckling. Regeln: en term får en sida bara om sajten redan använder den utan att förklara den, så att ordlistelänkningen i inläggen slår till och sidan får riktiga inkommande länkar. Sex klarade det och är publicerade på sv + en, i samma form som de sexton befintliga (term, kortdefinition på 1–2 meningar, två stycken, relaterade tjänster och termer): Kodagent (fem inlägg, båda AI-verktygen), AGENTS.md (fyra inlägg och ett helt verktyg), Plattform som produkt (fyra inlägg, ett med samma namn), Plattformsteam med Team Topologies-modellen (två inlägg, två tjänstesidor), Felbudget med SLO och SLI (SRE-definitionen använde ”SLO:er” och ”felbudgetar” oförklarat) och Ledtid (tre tjänstesidor, DORA-definitionen och Väntetidskalkylatorn). Brödtexterna länkar till inlägget eller verktyget där sajten redan talar om saken, med relativa adresser så att engelska läsare stannar på
/en; varje term har en fetad kärnmening och en extern källa (agents.md, Team Topologies, Googles SRE-bok). Tio befintliga termer har fått spegelreferenser tillbaka (MCP → Kodagent och AGENTS.md, Golden path → AGENTS.md, Platform engineering → Plattform som produkt och Plattformsteam, IDP → Plattform som produkt, Inner source → Plattformsteam, SRE och Observability → Felbudget, DORA → Ledtid och Felbudget, CI/CD och Trunk-based → Ledtid), så inga referenser är enkelriktade. Kontrollerat: alla referenser löser upp åt båda hållen, brödtexterna renderar genom sajtens Portable Text-pipeline utan kvarvarande markdown, och ordlistelänkaren träffar fyra av de sex i befintliga inlägg (Felbudget och Ledtid nås via SRE, DORA och tjänstesidorna). Valda bort: självbetjäning och incident (vardagsord), AI-assisterad utveckling (sajtens egen kategorietikett), mikrotjänster (bara i uppdrag, alla andra har sidan) och allt med noll omnämnanden på sajten — cognitive load, inner loop, toil, blue-green, SBOM, shift left, DDD, chaos engineering, context window, RAG, evals. Utvecklarportal/Backstage ligger på gränsen (tolv omnämnanden på DX-sidan, inget inlägg) och väntar på ett inlägg. Ordlistan har nu 22 termer; Dagens term roterar över alla. - Dagens term på startsidan. Ett kort mellan ”Senaste inläggen” och kontaktbandet (
TermOfDay): dagens datum, en term ur ordlistan som länk till/ordlista/<slug>och den korta definitionens första mening, plus ”Hela ordlistan →”. Vilken term det blir följer av datumet ensamt (lib/termOfDay.js): dygnet räknas i svensk tid viaIntl.DateTimeFormatmedEurope/Stockholm, så bytet sker vid midnatt i Sverige oavsett var besökaren eller Vercels byggmaskin står; termerna sorteras på slug (samma term på svenska och engelska, oberoende av svarsordningen från Sanity) och gås igenom i en blandad ordning som blandas om vid varje fullt varv, seedad med varvnumret (mulberry32 + Fisher–Yates), så varje term visas exakt en gång per varv och aldrig två dagar i rad. Första meningen klipps vid första punkt, utropstecken eller frågetecken som följs av versal, med undantag för förkortningar (”t.ex.”, ”e.g.”, ”etc.”) så att bara DORA-mätvärdena (två meningar) klipps i dag. Hela ordlistan (16 termer, 9,6 kB) seedas från prerendern med sammaGLOSSARY_LIST_QUERYsom/ordlista, så valet görs på besökarens dag även när ögonblicksbilden byggdes en annan dag; kortet har fast minsta höjd och textrutan tre reserverade rader (fem på mobil), så en kortare eller längre definition flyttar inget under. Laddningstillstånd och fel hanteras som ”Just nu”: platshållare i samma höjd, ingenting alls om hämtningen misslyckas utan seed. Två kolumner från 961 px (datum och term till vänster, meningen till höger), staplat därunder. Kontrollerat i Node: samma val oavsett indataordning, 64 dagar utan upprepning med alla 16 per 16-dagarsperiod, 80 000 dagar utan två lika i rad, och gränsen 2026-09-07 22:30 UTC räknas som den 8:e. Ur TODO:ns ”Startsidan: visa sådant som händer på andra ställen”.
- Drönarefoto med användningsfall, riktat till fastighetsmäklare. Tjänstesidan hade fyra korta generiska sektioner (259 ord). Nu inleder två nya: ”Bostadsförsäljning: visa läget, inte bara huset” — varför flygbilden är det som får en spekulant att klicka vidare (tomten, avståndet till vattnet, kvällssolen på altanen), vilket paket mäklaren får (stillbilder från olika höjder, översikt med markerad tomt, kort film för sociala medier och visning) och att vi utgår från Trosa och Stockholm — och ”Kommersiella fastigheter & tomter” (infarter, lastzoner, granntomten; gränser markerade som illustration, inte lantmäteriunderlag). Efter ”Tak & fasad” en sektion för bostadsrättsföreningar och fastighetsägare (underlag inför takrenovering och upphandling, daterad dokumentation), och sist ”Så går det till” (adress och syfte in, flygning planerad efter väder, ljus och luftrumsregler, leverans i format för webb, sociala medier, presentation och tryck, svar inom 48 timmar). Introt har fått en mening om mäklare, sökningstiteln är ”Drönarefoto för mäklare, bygg & inspektion” och meta description nämner mäklare, byggprojekt och fastighetsägare. Ny fotorealistisk sektionsbild i sidans stil: röd villa på stor tomt vid en sjö i kvällsljus, med alt-text. Svenska och engelska; 259 → 525 ord (en 608). Inga påståenden om priser, leveranstider eller certifieringar.
- Sexton uppdragssidor omskrivna och översatta. Uppdragen som låg under 100 ord (JNT, Eniro, Cellip, Signal Bredbånd, Nordiskt bevakningsföretag, Type2dialog, Musikindustrin, Norsk aktör – CRM-utbildning, Euroflorist, Fresh Fitness, Viamare, Bioindustri Norge, Global koncern, SKL, Kammarkollegiet och Vi-skogen) har fått nya svenska beskrivningar i Studio — bakgrund om kunden, roll, angreppssätt och ett utfallsstycke — och den engelska versionen är översatt stycke för stycke så att båda språken har samma antal stycken (4–11 per sida). Från 24–91 ord till 124–437 (sv). Alla 21 uppdrag publicerade, inga utkast kvar. Underlaget är kundernas egna presentationer och uppdragsbeskrivningarna; inga uppmätta utfall har lagts till. Där svenskan återger kundens presentation i ”vi”-form är engelskan skriven i tredje person, så att ”we” aldrig pekar på Paperphyte. Nordiskt bevakningsföretag anonymiserat på båda språken (kundnamn, tidigare koncern, år och huvudkontor strukna). SKL-sidan säger nu SKR (tidigare SKL). Type2dialog stavas som bolaget självt gör i brödtexten; titeln ”Type2Dialog ApS” oförändrad.
- Ny bransch: Tjänsteföretag. Viamare (marin service), Eniro (katalogföretag) och intresseorganisationen i musikindustrin låg under Telekom utan att vara telekombolag. Sjunde bransch ”Tjänsteföretag” / ”Service Businesses” (
/branscher/tjansteforetag, ledord ”CRM, affärssystem, integrationer”) iindustries.js, Studions branschlista ochllms.txt— startsidans rutnät,/branscher, prerender och sitemap följer med automatiskt, och siffran under heron räknar nu sju branscher. Ett ensamt sista kort i det trekolumniga rutnätet spänner över hela raden så sju kort inte lämnar tomma celler. Nyttindustry-dokument i Sanity med intro på sv + en (167/193 ord) i samma form som de sex andra: vad branschen kräver, de tre uppdragen med länkar, tjänsterna Produktutveckling och DevOps. De tre uppdragen flyttade; Telekom har kvar Cellip, JNT och Signal Bredbånd, vilket är precis de tre Telekom-introt nämner. Kod deployad före innehållet så att uppdragen aldrig saknade bransch på sajten. Studion deployad med det nya värdet. Meta description för den nya sidan: 141 tecken (sv), 147 (en). - E-postadressen är hello@paperphyte.se. Texten sa hej@paperphyte.com, men paperphyte.com har inga MX-poster alls — det har paperphyte.se (Proton). Bytt på kontaktsidan på båda språken.
- Kontaktsidan har fått text. Sidan prerendrade 72 ord: rubrik, ledtext och två kort. Under korten ligger nu tre block på svenska och engelska — ”Så går ett första samtal till” (WhatsApp eller hej@paperphyte.com, svar inom 48 timmar på vardagar, kort och utan åtagande, ett ärligt ja eller nej), ”Vad vi kan hjälpa till med” (de sex tjänsterna med en rad var, länkade) och ”Bra att veta” (litet kollektiv i Stockholm och Trosa sedan 2017, uppdrag från tvådagarsutbildning till fleråriga åtaganden, kunder i Sverige, Norge, Finland och Danmark, de fyra verktygen, och integritetspolicyn för det man skriver). Allt som påstås finns redan någon annanstans på sajten. 72 → 382 ord (en 78 → 398). Länkrenderaren för inline-markdown är utbruten till
inlineLinks.jsxoch delas med verktygssidornasToolAbout. - Inga dubbla titlar mellan svenska och engelska sidor. Sju sidpar delade titel: för uppdrag i SaaS & Startups är branschsegmentet samma sträng på båda språken, och för långa kundnamn (Kammarkollegiet, SKL) släppte
pageTitlebranschen före varumärkessuffixet så att bara kundnamnet blev kvar. Uppdragssidorna heter nu ”Kund — Uppdrag · Bransch — Paperphyte” respektive ”Client — Assignment · Industry — Paperphyte”, och hjälparen behåller hellre ett språkspecifikt segment (först det långa, sedan bara ”Uppdrag”/”Assignment”) än suffixet när allt inte ryms på 60 tecken — så ”Kammarkollegiet, Kapitalförvaltningen — Assignment” tappar Paperphyte men skiljer sig från svenskan. Samma grepp lyfte de kortaste titlarna: ”JNT — Telekom — Paperphyte” (26) är nu ”JNT — Uppdrag · Telekom — Paperphyte”. Cookies-policyns engelska rubrik är ”Cookie policy” i Sanity, i linje med ”Privacy policy”. Kontrollerat mot alla 149 sidor efter deploy: inga dubbla titlar, ingen över 60 tecken, sju under 30 (ordlistans ”Vad är GitOps?” och liknande, som är specifika nog). Sista punkten ur SEO-genomgången 2026-09-06. - Förklarande text under AI-redo-kollen och Repo-röntgen. De två verktygen prerendrade 63 respektive 155 ord statisk text — rubrik, ledtext och en knapp — så det fanns inget för en sökmotor att ranka på och inget för en läsare att bedöma verktyget efter. Ny sektion
ToolAboutunder verktyget, matad av ettabout-block i i18n: vad det mäter, de fyra delarna eller grupperna med vad var och en kollar, hur poängen läses (de riktiga trösklarna: 26/13 av 36 respektive 14/9 av 18), att inget lämnar webbläsaren, och vart man går sedan (Developer Experience och AGENTS.md-generatorn respektive generatorn och Delivery Engineering). Inline-markdown-länkar blir router-länkar. Svenska och engelska, 250–270 ord per verktyg. Live: AI-redo-kollen 63 → 334 ord (en 70 → 377), Repo-röntgen 155 → 407 (en 164 → 444). Väntetidskalkylatorn och AGENTS.md-generatorn låg redan på 400–500 ord och är orörda. Ur SEO-genomgången 2026-09-06. - Snabbare sidor på mobil: lättare bundle, responsiva bilder, inga laddningsblinkar. Tre delar ur SEO-genomgången. (1)
@sanity/clientersatt i webbläsaren av en 20 radersfetch-klient med sammasanityClient.fetch(query, params)-form (parametrar som JSON i$namn-querystring mot API-CDN:et); den officiella klienten drog med sig rxjs, get-it och stega-kod för skrivskyddad GROQ. Huvudbundeln 630 → 543 kB minifierad, 192 → 164 kB gzippad; byggskripten använder den officiella klienten i Node som förut. (2) Alla Sanity-bilder harsrcset(heroes 640–1600, kort 400/800) ochsizessom matchar sin container, så en mobil inte längre laddar 1600-pixlars heroes;preconnecttill bild-CDN:et och API-CDN:et iindex.html. (3) Detaljsidorna — uppdrag, tjänst, inlägg, ordlisteterm, policy, konsult, bransch och konsultindex — startade från ett laddningstillstånd vid första klientrenderingen och ersatte det prerendrade innehållet med ”…” tills svaret kom: uppmätt layoutskift 0,71 på mobil, synligt först när hämtningen blev snabbare. De startar nu från prerenderns seed (prerendered()/fetchSanity(), samma mönster som listsidorna) och faller bara tillbaka på laddningstillståndet vid klientnavigering till en annan slug. Konsultsidans CV-uppdrag hämtas utan seed (de matar bara PDF:en och hade lagt 150 kB i HTML:en) och branschfrågan bär inte längre beskrivningar som korten aldrig visar. Routebaserad kodsplittring övervägdes och valdes bort: appen monteras medcreateRoot().render(), så en lat route hade blankat den prerendrade sidan tills chunken kom, och sidorna är bara ~110 kB av bundeln. Lighthouse mobil på/uppdrag/viamare: 84 → 93, LCP 4,3 → 3,0 s, CLS 0, TBT 60 → 10 ms; tjänstesida 86, inlägg 93, alla med CLS 0. Verifierat live på sju detaljsidor: inget laddningstillstånd, inget skift. Startsidan ligger kvar på 79/LCP 4,0 s i simulerad slow-4G — dess LCP är hero-rubriken, bunden av anslutning, stylesheet och typsnitt; nästa steg där vore inlinad kritisk CSS. - Filterlisten på
/uppdragfastnar inte längre på mobil. Bransch- och rollfiltret varposition: stickyoch blev ~420 px högt på en 390 px bred skärm — halva skärmen — så uppdragen rullade in under det; sjunde branschchipet gav ännu en rad. Under 760 px rullar listen med sidan; på surfplatta och desktop är den fortfarande fäst. - Riktiga 404:or för okända adresser.
vercel.jsonskrev om alla okända adresser under/uppdrag,/konsulttjanster,/branscher,/konsulter,/anteckningsbok,/policy,/kontaktoch hela/entill SPA-skalet — status 200, skalets standardtitel, ochX-Robots-Tag: noindexsom var knuten till/_shell.htmlnådde aldrig de omskrivna adresserna; noindex kom först när JavaScript kört. Eftersom varje giltig route prerendras till en statisk fil gjorde omskrivningarna ingen nytta för riktiga sidor. De är borttagna: Vercel serverar statiska filer först och faller annars tillbaka pådist/404.htmlmed status 404, sidan med ”404 — Paperphyte”, noindex och länk hem. Verifierat live: 13 giltiga adresser (sv, en, verktyg med query) svarar 200 och sex påhittade svarar 404; 308-omdirigeringarna för/en/anteckningsbok/<slug>och avslutande snedstreck är opåverkade. Enda priset: en slug som publiceras svarar 404 för sökrobotar under minuterna fram till webhook-bygget, medan en människa som följer länken ändå får sidan renderad i webbläsaren. Ur SEO-genomgången 2026-09-06. - Språkväxlaren är en riktig länk. SV/EN i sidhuvudet var två knappar som bytte sida med
window.location.assign, så inte en enda av de 67 engelska sidorna gick att nå via länkar från den svenska sidan (och tvärtom) — sitemap och hreflang pekade ut dem, men bara länkar för vidare auktoritet. Nu två<a>medhreflang,langocharia-current, till samma sida på det andra språket, fortfarande som full sidladdning eftersom routerns basename är fast per dokument. Blogginlägg är enspråkiga, så där pekar EN på det engelska bloggindexet i stället för en adress som bara omdirigerar tillbaka. Utseendet oförändrat; mittenklick och ”kopiera länk” fungerar nu. Ur SEO-genomgången 2026-09-06. - CV-blurb på uppdragen. Nytt fält
cvBlurb(sv + en, tre rader) påassignment— en kort text för konsult-CV:t som inte visas på uppdragssidan. PDF-CV:t (CVDocument) visar nu blurben för det språket när den finns och faller annars tillbaka på beskrivningens första stycke som förut; ingen fallback över språkgränsen, så ett engelskt CV visar aldrig en svensk blurb. Fallbacken rensar inline-markdown, som annars hade lagt kundlänkarnas syntax i PDF:en. 21 svenska blurbar skrivna: en mening om kunden och tre om rollen, vad som byggdes och vad det gav (67–102 ord), hämtade ur beskrivningarna utan nya siffror. Engelska blurbar översatta från de svenska, mening för mening (81–113 ord), så att båda PDF-språken nu visar blurben för alla 21 uppdrag — verifierat genom att renderaCVDocumentmed CV-frågan och jämföra texten fält för fält. Studion deployad med fältet. - Hero-illustrationer på alla 21 uppdrag. Ingen uppdragssida hade någon bild; mallen renderade redan
heroImageöverst i artikeln och som delningsbild, så/uppdrag-länkar delades med sajtens standardbild. Nu en illustration per uppdrag i samma handritade linjestil som tjänstesidorna (krämfärgat papper, tunna bläcklinjer, dämpat mintgrönt och senapsgult, ingen text), 1376×768, genererade med Sanitys bildgenerator från en prompt per uppdrag som beskriver just det arbetet: kustkarta med båtar och kartnålar (Viamare), transportband genom tre stationer (Eniro), musiknot till faktura (musikindustrin), kalkylblad och arkivlåda in i en databas (bevakningsföretaget), radiomast över en fjord (Signal), whiteboard och runt bord utan människor (CRM-utbildningen) och så vidare. Alla har beskrivande alt-text på svenska och engelska (lokaliserat fält). Bilderna syns också i uppdragskorten på bransch- och tjänstesidorna och under ”Relaterade uppdrag”, och fallstudierna får delningsbild även om deras egen layout inte visar heron. Verifierat live på sv och en. - Länkar till kundernas webbplatser. Tio uppdragssidor som namnger kunden länkar nu till kundens egen sajt från första stycket, på båda språken: Cellip, Eniro-koncernen, Euroflorist, JNT, Kammarkollegiet, Signal, SKR, Star Stable, Type2dialog (plus Komponent i stycket om sammanslagningen) och Vi-skogen. Vanliga redaktionella länkar med
rel="noreferrer noopener", ingen nofollow, samma flik. Varje mål kontrollerat före och efter: alla elva svarar 200. Viamare fick ingen länk — viamare.se är parkerad hos Loopia och viamare.com är en brittisk färjebokare. De fem anonymiserade uppdragen och de fyra fallstudierna (annan brödtext) är orörda. Inlagt viasanity execmed krav på exakt en träff per fras, 22 spann. - Egna meta descriptions på uppdragssidorna. Nytt fält
seoDescription(localeString, varning över 160 tecken) påassignment; sidan läser det först, därefter fallrubrikens ingress och sist brödtexten som förut. Brödtextfallbacken rensar nu inline-markdown så länksyntax aldrig hamnar i en meta-tagg (gäller alla sidor som använderplainTextFromPortableText). 21 × 2 texter skrivna om arbetet — roll, vad som byggdes, teknik, kund där den är namngiven — på 135–160 tecken, inlagda viasanity execmed längdkontroll och verifierade live på alla 42 sidor. Före: de första 155 tecknen ur beskrivningen, som på elva sidor var kundens bakgrund klippt mitt i meningen (”Eniro-koncernens verksamhet bedrivs inom två affärsområden. Affärsområdet Marketing Partner, som stod för 64 procent…”). Efter: ”Delivery Engineer hos Eniro under ett pressat SugarCRM-införande: automatiserad releasesättning och ett snabbare test- och utvecklingsflöde med färre handgrepp.” Studion deployad med fältet. - Interna länkar på uppdragssidorna. De 17 vanliga uppdragssidorna hade noll länkar i brödtexten och fyra i hela huvudinnehållet (brödsmulor + kontakt); sex av dem (Euroflorist, Fresh Fitness, Type2dialog, bioindustribolaget, bevakningsföretaget, norska CRM-utbildningen) hade inga inkommande innehållslänkar alls, elva bara en från branschintrot, och tjänstesidorna länkade inte till ett enda uppdrag. Tre lager, i mall och innehåll: (1) En roll→tjänst-mappning (
lib/roleServices.js: DevOps → DevOps, Delivery Engineer → Delivery Engineering, Fullstack/Back-end → Produktutveckling, Cloud Ops/SRE → Plattformsteknik) används åt båda hållen — rollchipsen på uppdragssidan länkar till tjänsten, och varje tjänstesida får ”Uppdrag där vi gjort det här” med de sex senaste uppdragen bemannade med dess roller plus länk till registret (drönarefoto och Developer Experience saknar roll och visar inget). ”Relaterade uppdrag” under varje vanligt uppdrag: tre syskon, samma bransch först, sedan flest delade tekniker, i samma GROQ-anrop som uppdraget; fallstudierna behåller sin redaktionella lista. Uppdragskortet utbrutet tillAssignmentCard, som branschsidan nu också använder. (2) Branschintrona för SaaS & Startups och Offentlig sektor har fått en mening var som länkar de sex olänkade uppdragen. (3) Uppdragets brödtext renderas nu med samma Portable Text-renderare som blogg, bransch och tjänstesidor (transformBody+ delade komponenter), så inline-markdown-länkar, fetstil och kodblock fungerar — och 46 länkar (23 per språk, 1–2 per sida) ligger nu i texterna på 15 uppdrag: tjänstesidan där texten redan nämner arbetet (”interaktiv kartfunktion”, ”releasesättningsprocessen”, ”Continuous Delivery”) och tre korslänkar mellan uppdrag med samma teknik (Kammarkollegiet → musikindustrin om Agresso, SKL → Vi-skogen om mikrotjänster, bioindustri → SKL om fältarbete). Länkarna lades in med ett skript viasanity execsom krävde att varje fras förekom exakt en gång; norska CRM-utbildningen fick ingen textlänk eftersom ingen fras passade. Uppmätt före/efter på/uppdrag/viamare: 4 → 9 länkar i huvudinnehållet, varav 5 kontextuella. Ordlistelänkning slogs inte på för uppdrag: termerna träffar bara ”CI/CD” på tre fallstudier. Ännu inte gjort: externa länkar till namngivna kunder, hero-bilder, och ett egetseoDescription-fält (meta description är i dag de första 155 tecknen, som på elva sidor nu är kundens bakgrund). - Småfel i de nya uppdragstexterna rättade (sv, publicerade): osynliga mjuka bindestreck (U+00AD) från skr.se borta ur SKL-sidans ”attrahera” och ”kompetensförsörjningen”; ”en annan säkerhetskoncernen” → ”en annan säkerhetskoncern” på Nordiskt bevakningsföretag; Kammarkollegiets ”finns hos oss” (myndighetens egen röst) → ”finns hos myndigheten”, och Allmänna arvsfonden med stort A.
- Tre senaste inläggen på startsidan. Sektion före kontaktbandet (
LatestPosts): kategori, titel, utdrag, datum och lästid i samma lässlistekort som/verktygoch relaterade inlägg, viaPostLink(oprefixade adresser på/en). NyLATEST_POSTS_QUERY, seedad från prerendern. - Siffror under heron. ”21 uppdrag · 6 branscher · sedan 2008” som en dämpad rad under knapparna, räknat ur uppdragsregistret (
SITE_STATS_QUERY: antal, unika branscher, tidigaste startdatum) — inga inskrivna siffror. Uppdrag och branscher länkar till sina sidor. Seedad från prerendern; den befintliga.hero__meta-stilen används. - Verktygen på startsidan. Ny sektion mellan Fallstudier och Branscher (
ToolsRow), så att ljusa och mörka band växlar: de fyra verktygen i en rad med namn, meta och ledtext ur samma i18n som/verktyg, plus länk dit. Statisk — ingen hämtning, inget layoutskift. - Fallstudier på startsidan. Två kort mellan Åtaganden och Branscher (
FeaturedCases): de två förstafeatured-uppdragen i redaktörens ordning, i samma mörka kort som/uppdragmed problem och angreppssätt, plus länk till hela registret. NyFEATURED_CASES_QUERY, seedad från prerendern så korten finns från första renderingen. - Öppna flikar överlever deployer. Varje bygge bytte namn på alla chunkar (bygginfon låg inbakad i index-chunken via
define, och html2pdf-chunken importerar därifrån), så en flik från förra bygget fickFailed to fetch dynamically imported modulevid ”Ladda ner CV”. Två åtgärder:reloadOnStaleChunk.jslyssnar på Vitesvite:preloadErroroch laddar om sidan en gång (spärr i sessionStorage mot omladdningsloop), och bygginfon (deploytid, commit, changelog) levereras nu som/build-info.jsonoch/changelog.jsoni stället, så JS-hasharna är stabila mellan byggen med oförändrad kod, t.ex. de som Sanity-webhooken triggar. Sidfotens stämpel och/andringarseedas från prerendern via databryggan. 46 kB changelog försvann samtidigt ur huvudbundeln. - Lokala dev-stacken. nginx faller tillbaka på SPA-skalet för kataloger utan
index.html(/anteckningsbok/gav 403 eftersom RSS-flödet skapar katalogen), ny.dockerignorehindrar värdensnode_modulesfrån att skriva över containerns vid bygget, och efter beroendeändringar krävspodman-compose build frontend-watch frontend && podman-compose up -d --force-recreate. - Databryggan på fler listsidor.
/anteckningsbok,/uppdrag,/ordlistaoch/verktyg(lässlistan) startar nu från prerenderns Sanity-svar viaprerendered()/fetchSanity()i stället för tomt tillstånd, samma mönster som startsidan. Misslyckas den efterföljande hämtningen behålls det seedade innehållet. Mätt lokalt på prerendrad bundle med slow-4G/4× CPU: CLS 0 på alla sex rutter (sv + en), listorna på plats från första renderingen. Seeden väger 3–16 kB per sida. Bloggens synkronasetStatei effekten togs bort på köpet (lint 26 → 24 sedan i morse). - Branschsidorna har fått innehåll. Ny dokumenttyp
industryi Sanity (slug som matcharsrc/lib/industries.js, lokaliserat intro, referenser till tjänstesidor)./branscher/<slug>hämtar dokumentet vid sidan av uppdragen och visar introt plus ”Tjänster som hör hit” ovanför uppdragslistan; saknas dokument ser sidan ut som förut. Sex intron skrivna och publicerade (sv + en, 125–178 ord vardera), tre stycken per bransch: vad branschen kräver, vad vi gjort där med länkar till uppdragen, och vilka tjänster som hör dit — allt hämtat ur uppdragsbeskrivningarna, inga nya siffror. Sidorna går från 42–88 ord till runt 200. Portable Text-länkar som börjar med/renderas nu som router-länkar (håller sig på/enpå engelska sidor, klientnavigering) — gäller även inläggen. Webhooken omskapad medindustryi filtret. Studion deployad med typen. - Beskrivningar på 135–160 tecken där de var korta. Kontaktsidan har fått en egen
seoDescriptioni i18n (sv 158, en 151) i stället för den korta ledtexten; branschsidornas mall säger nu vad sidan innehåller (”Paperphytes uppdrag inom branschen: plattformsteknik, DevOps och produktutveckling i drift”) i stället för ”Se Paperphytes uppdrag…”, 135–160 tecken för alla sex branscher på båda språken; policysidornas underrubriker i Sanity (som också är sidornas meta description) utökade till 142–160 tecken (sv + en, publicerade). Uppföljning av titelfixen mot produktion: 147 sidor i sitemap, 0 titlar över 60 tecken. - Titlar inom 60 tecken. Nytt fält
seoTitlepåblogPost(schema + sidfråga) och en regel iuseSeo-hjälparenpageTitle(): ” — Paperphyte” läggs bara till när hela titeln ryms i 60 tecken, annars visas titeln utan suffix; uppdragssidor tappar först branschsegmentet, sedan suffixet. Sju inlägg vars titel ensam är över 60 tecken har fått kortaseoTitlei Sanity (helgprojekt, reaktioner, agent-inlägget, Claude Design-loopen, IAM Roles Anywhere, QRGeno, plattform som produkt). Verktygens och uppdragsindexetsseoTitlei i18n kortade så suffixet ryms; Plattformsteknik (en) och Delivery Engineering (sv + en) trimmade med några tecken i Sanity. Studion deployad med det nya fältet. Fallstudier visar ”Kund: fallrubrik” bara när det ryms, annars uppdragstitel + bransch. Verifierat lokalt: 16 tidigare för långa sidor ligger nu på 36–60 tecken. - Engelska inläggs-URL:er borta.
/en/anteckningsbok/<slug>(aldrig prerendrad, men länkad 15 gånger från engelska bloggindexet, från startsidans remsa och från/en/verktyg) svarar nu 308 till/anteckningsbok/<slug>viaredirectsivercel.json. NyPostLink-komponent: på engelska sidor renderas inläggslänkar som vanliga<a href>till den oprefixade adressen (routerns/en-basename skulle annars prefixa varje<Link>), medhreflang/langsatt till inläggets språk; på svenska sidor är det fortfarande klientnavigering. Används i bloggindexet (utvalt + lista), ”Just nu”-remsan, verktygssidans lässlista och relaterade inlägg.useSeo: sidor utan språkpar (alternates: false) kanoniseras alltid till den oprefixade URL:en, så ett engelskspråkigt inlägg aldrig pekar sin canonical mot en adress som omdirigerar. - SEO-fixar efter genomgång av sajten. (1) Startsidans layoutskift: uppmätt CLS 0,27–0,54 på mobil (Sanity-sektionerna monterades tomma vid hydrering och ”Just nu”-remsan sköt ner allt under sig). Ny prerender-databrygga: klienten hämtar via
fetchSanity, prerendern serialiserar svaren till<script id="__sanity" type="application/json">i ögonblicksbilden, ochprerendered(query)ger komponenterna samma data som starttillstånd —ServicesochJustNuhydreras nu med innehåll. Remsans celler har fast minsta höjd (150px) och en platshållare med samma mått när seed saknas. Uppmätt efteråt: CLS 0,000 på/och/en. (2) Mjuka 404:or: alla sju detaljsidor sätterrobots: noindex, follownär slugen inte finns, ochuseSeotar bort en tidigarerobots-meta när nästa route inte begär någon (så en 404 inte läcker in vid klientnavigering);/_shell.htmlfårX-Robots-Tag: noindex. (3)trailingSlash: falseivercel.json—/en/och/konsulttjanster/blir 308 i stället för dubbletter. (4) Säkerhetsrubriker på Vercel:X-Content-Type-Options,X-Frame-Options,Referrer-Policy(samma som inginx.conf; CSP:n där är inaktuell — nämner fonts.googleapis men inte Matomo eller api.github.com — och kopierades inte). Bonus:PRERENDER_ONLY=/,/enrenderar ett urval lokalt. Verifierat i headless Chrome mot lokalt prerendrad bundle med slow-4G/4× CPU. - ”Var det här användbart?” på verktyg och ordlistetermer (
Useful-komponenten): en ja/nej-fråga längst ner på AI-redo-kollen (i resultatvyn), Väntetidskalkylatorn, AGENTS.md-generatorn, Repo-röntgen och varje/ordlista/<term>. Återanvänder reaktionsbackenden (api/react.js, Upstash) oförändrad: ja/nej lagras somlike/dislikeunder namnrymda slugs (verktyg-<route>,ordlista-<slug>) så de aldrig krockar med ett inlägg —GET /api/react?slug=verktyg-repo-rontgensvarar på vilka verktyg som är värda att bygga vidare på. Ett svar per webbläsare (minns ipaperphyte_reactions), byte och ångra fungerar, räknare visas, tack-rad efter svar, samma spärr på 20 anrop per IP och tio minuter. Gemensam plumbing flyttad tillsrc/lib/reactions.js(bloggensReactionsanvänder samma). Cookies- och integritetspolicyn uppdaterade (sv + en, publicerade): lokal lagring och Upstash-räknarna gäller nu även verktyg och ordlistetermer; verktygslistan i cookies-policyn nämner alla fyra verktyg. Verifierat i headless Chrome mot bundlen medcreateHandlersoch en Redis-fejk i minnet: ja → byt till nej → ångra → ja + omladdning behåller valet; bloggens reaktioner opåverkade. - Relaterade inlägg under varje inlägg. Tre kort längst ner (”Läs vidare / Relaterade inlägg.”) med de inlägg som delar flest taggar med det lästa, vid lika många taggar det nyaste först; inlägget självt utesluts och sektionen döljs när inga taggar delas. Ny
RELATED_POSTS_QUERY(count(tags[@ in $tags])i GROQ), korten återanvänder.tools-reading-kortet från/verktygplus en ny metarad med datum och lästid. Svaret nyckelas på slug så gamla kort inte ligger kvar vid klientnavigering mellan inlägg. - Ändringssida
/andringaroch deploy-stämpel i sidfoten. Hela den här changeloggen visas nu på en egen sida, dag för dag med underpunkter och kodspann intakta, och sidfoten har fått en rad ”Senast deployad 5 sep. 2026 21:02 · 1934279” som länkar dit. Allt bakas in vid bygget via Vitedefine(scripts/build-info.js→__BUILD_INFO__, läses isrc/lib/buildInfo.js): inga anrop till GitHub från besökarens webbläsare, ingen rate limit, fungerar även om repot är privat. Parsern tar## YYYY-MM-DD, punkter och underpunkter; inline-markdown (kod, fet, länkar) blir riktiga element, inga HTML-strängar. Sidchromet är tvåspråkigt, loggen svensk. Med i prerender, sitemap ochllms.txt. SaknasCHANGELOG.mdi byggmiljön (t.ex. en Docker-kontext som bara innehållerfrontend/) visar sidan en tom-text och stämpeln länkar ändå. Commit-hash frånVERCEL_GIT_COMMIT_SHAellergit rev-parse. Ett första utkast la de tre senaste posterna som block på startsidan; det ströks — startsidan är en säljsida, och tre teasers utan länk gjorde inte loggen mer läst. - Alt-text på tjänstesidornas hero-bilder (Sanity, publicerat): plattformsteknik, devops, developer-experience, produktutveckling och delivery-engineering saknade alla alt-text; nu beskrivande svensk alt-text per bild (laptop med konfetti, moduler i rörledningar, idé→flöde→app, leveransloop med hjärtkurva, pipeline med tre grindar och kanariefågel). Även de sju sektionsbilderna på plattformsteknik (kuber, kluster-rutnät, vågformer med avvikelse, nätverksdiagram) och produktutveckling (passare på pappersark, MCP-nav med databas/dokument/verktyg/kod, pratbubbla med gnistor) har fått alt-text. Samtliga bilder på tjänstesidorna har nu alt-text.
- ”Just nu”-remsa på startsidan (
JustNu-komponenten, mellan hero och Åtaganden): senaste inlägget med kategori, datum, lästid och reaktionsräknare (ReactionsSummary), nyaste verktyget och senaste uppdraget — tre celler i samma 1px-rutnät som tjänstekorten, staplade under 960px. Data från en nyJUST_NU_QUERY(sex senaste inläggen + senaste uppdraget); klienten väljer första inlägget på besökarens språk och faller tillbaka på det nyaste. Verktygslistan flyttad tillsrc/lib/tools.jsmedadded-datum så både/verktygoch remsan läser samma lista. Renderar ingenting tills Sanity svarat, och ingenting alls om anropet misslyckas. - Ordlistelänkar i inlägg. Första omnämnandet av varje ordlisteterm i ett inläggs brödtext blir en prickad länk till
/ordlista/<slug>med kortdefinitionen som tooltip vid hover/fokus (src/lib/glossaryLinks.js+GlossaryMark). Bara vanliga stycken och listpunkter — inte rubriker, citat, kod eller inne i befintliga länkar — och varje term högst en gång per inlägg. Termer på formen ”Namn (FÖRK)” matchar långformen eller förkortningen (förkortningen skiftlägeskänsligt); termer på fyra tecken eller mer får ett kort böjningssuffix (”golden paths”, ”plattformen”). Ordlistan hämtas en gång per sidladdning. På pekskärm finns ingen tooltip; länken går till definitionen. - Nytt verktyg: Repo-röntgen (
/repo-rontgen+/en/repo-rontgen). Klistra in ett publikt GitHub-repo (URL,org/repoeller git-remote) och få arton kontroller i fyra grupper — onboarding (README, AGENTS.md/CLAUDE.md, CONTRIBUTING, .editorconfig, devcontainer), reproducerbart bygge (låsfil, Dockerfile/compose, Makefile/justfile/package.json, fastnålad verktygsversion), kontroller & automation (CI, pre-commit, Dependabot/Renovate, CODEOWNERS, PR-mall) och puls (licens, push senaste 90 dagarna, ingen öppen PR äldre än 30 dagar, inte arkiverat) — med poäng av 18, tre nivåer (Frisk / Under observation / Remiss), vad som letades efter per kontroll, pulsfakta och ett ”Nästa steg” som pekar på AGENTS.md-generatorn när AGENTS.md saknas och Delivery Engineering när CI saknas. Fyra anrop direkt från webbläsaren tillapi.github.comutan inloggning (repo, rotlistning,.github/-listning, öppna PR:ar); bara rotkatalogen och.github/på standardgrenen läses. Delbar länk via?repo=org/reposom kör vid sidladdning. Logiken ligger isrc/lib/repoXray.js, sidan iRepoRontgenPage.jsxpå.vk-*/.ark-*-chassit plus nya.rx-*-klasser. Felläge för ogiltig adress, 404, GitHubs anonyma gräns (60 anrop/timme) och nätverksfel.- Inkopplad på alla nio ställen: route,
tools.js, i18n (rontgen,toolsPage.tools.rontgen,toolCta.rontgen;/verktyg-ledtexten säger nu ”Fyra sätt”), prerender, sitemap,llms.txt, ochToolCTApå tjänstesidan DevOps. - Verifierat i headless Chrome mot den byggda bundlen: startsidans remsa (sv/en, mobil), ordlistelänkar på tre inlägg (tooltip, inga länkar i rubriker eller nästlade), Repo-röntgen med inspelade GitHub-svar för
vitejs/vite(12/18) samt ogiltig adress och 404. Lint: 25 fel (26 sedan tidigare, inga nya). - Integritetspolicyn uppdaterad i Sanity (sv + en, publicerad): nytt stycke under ”När du besöker den här webbplatsen” om att Repo-röntgen anropar
api.github.comdirekt från webbläsaren (fyra anrop per repo, GitHub ser IP-adress och repo, Paperphyte ser inget, inget sparas, inga anrop förrän besökaren klistrar in ett repo); GitHub, Inc. (USA) tillagd under ”Vem vi delar uppgifter med”; rättslig grund (berättigat intresse, 6.1 f) förtydligad för GitHub-anropen.
- Inkopplad på alla nio ställen: route,
- Hela tjänstekortet klickbart. Åtaganden-korten (startsidan och
/konsulttjanster, sammaServices-komponent) länkar nu i sin helhet till tjänstesidan, inte bara titeln och "Läs mer"-knappen. Stretched link-mönstret i CSS: titellänken får ett::after-lager som täcker kortet, knappen ligger kvar ovanpå med egen hover och fokusring, och titellänken har fått en:focus-visible-ram. Ingen markup ändrad — skärmläsare och tangentbord ser fortfarande två vanliga länkar. Baksidan: texten i korten går inte längre att markera med musen. - Hero-ledtexten avslutas nu med "…drifta digitala produkter." — "— utan teaterföreställning." / "— without the theatre." struket ur sv/en i18n. Frasen fanns aldrig i Sanity.
- Ny bloggpost publicerad: "Er nästa plattformsanvändare är en agent — och den läser inte wikin" (
/anteckningsbok/plattformsanvandaren-ar-en-agent, kategori DX, 5 min). Tesen: en kodagent beter sig som en nyanställd på dag ett, varje dag, utan kollega att fråga — den läser bara det som finns i repot, gissar i stället för att fråga, kör kommandon i stället för att klicka och lär sig av felmeddelanden. Det gör den till den ärligaste DX-mätaren en organisation har, och inlägget beskriver vad en golden path behöver för att fungera utan tyst kunskap (kontraktsfil i repot, CI-kontroller körbara lokalt, felmeddelanden som specifikation, sandlådor med kortlivade rättigheter). Länkar vidare till golden paths-, plattform som produkt- och IAM Roles Anywhere-inläggen, AI-redo-kollen och tjänstesidan Developer Experience. Genererad hero-bild i sajtens isometriska stil med svensk alt-text.- Featured flyttad: den nya posten ligger nu i hero-slotten på
/anteckningsbok; "Sluta skriva wiki-sidor, börja bygga golden paths" är avflaggad. Exakt ett inlägg är featured. - Inlägget använder inline-markdown (
**fet**,[text](url)) i span-texterna, på samma sätt som Väntetidskalkylator-posten;transformBodyifrontend/src/lib/portableText.jsxexpanderar dem.
- Featured flyttad: den nya posten ligger nu i hero-slotten på
- Integritetspolicy och cookies-policy uppdaterade i Sanity (sv + en, publicerade) efter genomgång mot hur sajten faktiskt beter sig:
- Google Fonts/Google LLC struket överallt — typsnitten har varit self-hostade sedan 2026-07-25. Båda policyerna säger nu att typsnitten ligger på egen domän.
paperphyte_langstruket ur cookies-policyn: språket följer av URL:en (/en/), inget lagras. Endastpaperphyte_consentfinns i localStorage.- Ny cookie deklarerad:
mtm_consent_removed— sätts av Matomo vid nej i cookie-rutan (forgetConsentGiven), livslängd 30 år enligt matomo.js. - Nytt avsnitt i integritetspolicyn: "När du skriver till oss på WhatsApp" (Meta Platforms Ireland som mottagare, metadata, alternativ). Meta tillagd under "Vem vi delar uppgifter med", liksom QRGeno (kontaktsidans QR-kod går via
api.qrgeno.comsom loggar skanningar innan vidarebefordran till LinkedIn). - Tredjepartsleverans förtydligad:
matomo.jshämtas fråncdn.matomo.cloudvid varje sidladdning oavsett samtycke (IP i InnoCrafts CDN-loggar, ingen spårning); bilder fråncdn.sanity.ionämns bredvidapicdn.sanity.io; verktygssidorna sparar ingenting.
- Nytt verktyg: AGENTS.md-generatorn (
/agents-md-generatorn+/en/agents-md-generatorn) — nio frågor om ett repo (vad det är, kommandon, om CI:s kontroller går att köra lokalt, vägen till produktion, grenar/commits, läs-först-filer, regler, fråga-först och vad agenten får göra utan att fråga) blir en färdigAGENTS.mdellerCLAUDE.md, på engelska eller svenska, att kopiera eller ladda ner. Tomma fält utelämnas ur filen; en radräknare säger till över 70 rader ("mer än en sida"). „Visa ett exempel" fyller i ett realistiskt repo på filens språk. Allt genereras lokalt, inget sparas.- Byggd på
.vk-*-chassit från Väntetidskalkylatorn plus nya.amg-*-klasser (textfält, pill-val, förhandsvisning). Filens egna strängar ligger i koden (FILE.sv/eniAgentsMdGeneratornPage.jsx) eftersom filspråket väljs oberoende av sajtspråket; UI-copyn ligger i i18n underagentsmd. - Listad på
/verktyg(ledtexten säger nu "Tre sätt"), i sitemap, prerender (bilingual) ochpublic/llms.txt— som fått en ny sektion "Free tools"; verktygen saknades där helt. ToolCTApå tjänstesidan Developer Experience byter från Väntetidskalkylatorn till generatorn; Plattformsteknik behåller kalkylatorn.- Smoke-testad i headless Chrome mot den byggda bundlen (sv/en UI, båda filspråk, båda filnamn, tre verktyg listade på
/verktyg). Lint: inga nya fel (26 sedan tidigare, oförändrat).
- Byggd på
- Död newsletter-copy borttagen ur
footeri sv/en i18n — inget formulär har någonsin renderat den. - Lanseringsbloggpost publicerad i Sanity ("AGENTS.md-generatorn: sidan kodagenten läser först",
/anteckningsbok/agents-md-generatorn, kategori DX, flaggadshowOnToolsPage) med genererad hero-bild. Agent-posten länkar nu till generatorn i steg 2 av "Så börjar du". - Dela-knapp på alla blogginlägg. Ny komponent
SharePostlängst ner i varje inlägg (rad med etiketten "Värt att skicka vidare?", knappen "Dela inlägget" och tillbaka-länken). Användernavigator.share()med inläggets titel, ingress och kanoniska URL där webbläsaren har Web Share API (mobil, Safari, Edge); annars kopieras länken till urklipp och knappen visar "Länken är kopierad" i 2,5 s. Avbrutet delningsark ignoreras tyst; blockerat urklipp faller tillbaka påexecCommand('copy'). sv + en. Verifierad i headless Chrome (fallback-vägen, urklippet fårhttps://paperphyte.com/anteckningsbok/<slug>även från/en/-URL:en, eftersom inlägg är enspråkiga). - Reaktioner på blogginlägg (gren
feat/reactions): fyra räknare — 👍 gilla, 👎 ogilla, ❤️ älska, 👏 applådera — längst ner i varje inlägg, ovanför dela-raden. Klick räknar upp, klick igen tar tillbaka; gilla och ogilla utesluter varandra. Optimistisk uppdatering med rollback vid fel; vid 429 visas en vänlig notis.- Ny backend: Vercel Function
frontend/api/react.js(GET ?slug=→ räknare,POST {slug, kind, delta}→ uppdaterade räknare) mot Upstash Redis: en hash per inlägg (reactions:<slug>,HINCRBY= atomärt), plus sorted setreactions:topmed totalen per inlägg för en framtida riktig "Populärast"-sortering. Sliding-window-rate-limit 20 reaktioner per IP och tio minuter via@upstash/ratelimit; inget om besökaren lagras med räknaren. Klient och limiter är injicerbara (createHandlers) och testade mot en in-memory-fake (8 fall: validering, inkrement, take-back ej under noll, 429 per IP, 503 utan konfiguration). - Frontend:
Reactions.jsx(visas först när räknarna laddats; döljs helt om API:et svarar fel/503), i18nblogPage.reactions*, CSS.post-reactions*. Vilka reaktioner webbläsaren gett sparas i localStorage underpaperphyte_reactions— artighet, inte säkerhet. - E2E i headless Chrome mot byggd bundle med den riktiga handlern på fake-Redis: toggle, take-back, gilla↔ogilla, persistens efter reload, ny besökare, engelska etiketter, 429-rollback, 503 → dolt.
- Innan merge/deploy: (1) Upstash Redis är kopplat via Vercel Marketplace; integrationen injicerar
KV_REST_API_URL/KV_REST_API_TOKEN(plusKV_REST_API_READ_ONLY_TOKEN,KV_URL,REDIS_URLsom inte används). Funktionen läser både de namnen och Upstashs egnaUPSTASH_REDIS_REST_URL/_TOKEN; utan något av paren svarar endpointen 503 och sidan döljer knapparna, så deploy är ofarlig. Kontrollera att variablerna är aktiverade för både Production och Preview i Vercel. (2) Policyerna är uppdaterade och publicerade i Sanity:paperphyte_reactionsi cookies-policyns localStorage-lista (plus ett stycke om räknarna under "Tredjepartsleverans"), och i integritetspolicyn ett stycke under "När du besöker", Upstash, Inc. (USA; databas i EU) under "Vem vi delar uppgifter med" samt missbruksskyddet i "Rättslig grund" — allt sv + en. (3) ESLint har fått ett block förapi/**(Node- + webbglobaler).
- Ny backend: Vercel Function
- Ny sida: Verktyg (
/verktyg+/en/verktyg) — samlingssida för sajtens självbetjäningsverktyg (AI-redo-kollen och Väntetidskalkylatorn) med format, tidsåtgång och vad man får ut av vart och ett. Verktygen är kodade, inte innehåll: URL:erna ligger iTOOLSi sidan, copyn i i18n. ItemList-JSON-LD, hreflang och prerender som övriga sektionssidor.- Nytt fält på
blogPost:showOnToolsPage(bool). Inlägg som flaggas dyker upp i sektionen "Bakgrunden till verktygen" längst ner på sidan, sorterade på publiceringsdatum. Sektionen döljs helt när inget inlägg är flaggat. Fältnamnet är camelCase eftersom det är en objektnyckel i dokumentet och i GROQ — bindestreck skulle falla på schemavalidering. Studion behöver deployas om för att växeln ska synas i redigeringsgränssnittet (cd content-studio && pnpm deploy). - "Verktyg" tillagd i footerns Företag-kolumn (sv + en). Huvudnavigationen är oförändrad — den ligger kvar på fem poster.
- Nytt fält på
- Nytt verktyg: Väntetidskalkylatorn (
/vantetidskalkylatorn+/en/vantetidskalkylatorn) — räknar om väntan på bygget till förlorade utvecklartimmar och kronor per år. Tre reglage (utvecklare, byggen per dag, minuter per bygge) plus två redigerbara antaganden (andel av väntan som går förlorad, standard 60 %, och kostnad per utvecklartimme, standard 850 kr). Utlåtande i tre nivåer (Ni har anställt väntan / Det syns i marginalen / Det här är inte er flaskhals) med nästa steg som länkar till DeLaval-fallstudien, plattformsteknik, Developer Experience, ordlistan och AI-redo-kollen. Allt räknas lokalt, inget sparas.- Matematiken visas öppet på sidan ("Så räknar vi") med varje mellansteg — samma hållning som de streckade "siffra saknas"-rutorna på fallstudierna. 220 arbetsdagar och 1 600 timmar per heltidstjänst, båda avrundade nedåt.
- Knappen "Kopiera länk med era siffror" lägger inmatningen i query-strängen (
?dev=&b=&min=&spill=&kr=) så resultatet kan skickas vidare till den som äger budgeten. Sidan läser tillbaka värdena vid inläsning; ogiltiga eller orimliga värden faller tillbaka på standardvärdet. ToolCTA-banner med nyckelnvantetidpå DeLaval-fallstudien samt på tjänstesidorna Plattformsteknik och Developer Experience.KonsulttjanstPagehar fått sammaTOOL_CTA_BY_SLUG-mekanism somAssignmentPage; bannern renderas mellan tjänstebeskrivningen och processavsnittet, och bara när dokumentet är inläst.- CSS-sektionen
/* AI-REDO-KOLLEN */heter nu/* TOOL PAGES */; den gemensamma verktygschromen delas mellan.ark-*och.vk-*i stället för att dupliceras. - Sidan ingår i sitemap och prerender (bilingual; 133 rutter totalt).
- Lanseringsbloggpost publicerad i Sanity ("Väntetidskalkylatorn: vad kostar er väntan på bygget?",
/anteckningsbok/vantetidskalkylatorn, kategori DX) med genererad hero-bild. OBS: posten publicerades innan verktyget deployats — dess länkar till/vantetidskalkylatornger 404 tills koden är ute. - OBS:
localhostligger inte i projektets CORS-lista, så Sanity-drivna sidor renderar inte i utvecklingsläge utan att API-anropet proxas. Verifieringen av ToolCTA-placeringen gjordes med en sådan proxy — lägg till en dev-origin i CORS-listan om det ska gå att köra lokalt utan omvägar.
- Nytt blogginlägg med kortkommandon för skärmdumpar
- Nytt verktyg: AI-redo-kollen (
/ai-redo-kollen+/en/ai-redo-kollen) — tolv frågor i fyra dimensioner (skyddsräcken i koden, testgrinden, reproducerbarhet, arbetssätt & ansvar) som visar om en kodbas är redo för AI-assisterad utveckling. Utlåtande (Grinden håller / glappar / saknas), dimensionsanalys och rekommendationer som länkar till QRGeno-fallstudien, tjänstesidor och ordlistan. Allt räknas lokalt; svarsordningen slumpas.- Ny återanvändbar komponent
ToolCTA— drop-in-banner för verktyg på valfri sida (i18n-driven). Placerad på QRGeno-fallstudien. - Lanseringsbloggpost skriven som utkast i Sanity ("AI-redo-kollen: är er kodbas redo att koda i par med AI?",
/anteckningsbok/ai-redo-kollen) med genererad hero-bild — publicera den när verktyget är deployat, annars länkar den till en 404. - bloggpost published
- Ny återanvändbar komponent
- Fyra fullständiga fallstudier på
/uppdrag/atg,/uppdrag/delaval,/uppdrag/qrgenooch/uppdrag/urb-it(sv + en), implementerade från Claude Design-utkasten "Fallstudie *".- Uppdrag med fallstudieinnehåll renderar nu en komplett fallstudielayout: hero med faktaruta (kund/period/roller/åtagande), innehållsförteckning, numrerade sektioner (problem, angreppssätt, beslut, utfall, teknik), mörka citatband och relaterade uppdrag.
- Nya Sanity-typer (
caseSection,caseBlock,caseItem,caseQuote,caseRelated) plus fält på assignment (caseTitle,caseLead,caseService,caseSections,caseRelated) — allt innehåll ligger i Sanity, tvåspråkigt, publicerat. - ATG:s teknikförteckning kompletterad med Nexus, SonarQube, Prometheus och Grafana (enligt designens anteckning).
- Utfallsmått utan verifierad siffra visas i streckade "siffra saknas"-rutor (DeLaval har riktiga siffror: 1 000 parallella tester, 30 000 vCPU-timmar/mån, 80 000 byggen/mån). Studion behöver deployas om för de nya fälten.
- Ny sida: Uppdrag (
/uppdrag+/en/uppdrag) — hela uppdragsregistret (21 uppdrag) med filtrering på bransch och roll, fritextsök på teknik/kund, statistik i hero och en mörk "Fallstudier"-sektion med fyra utvalda uppdrag (DeLaval, QRGeno, ATG, Urb-it). Implementerad från Claude Design-utkastet "Uppdrag Index", mappad till sajtens designtokens.- Assignment-schemat utökat med
featured,featuredOrderoch fallstudiefält (caseProblem/caseApproach/caseOutcome, sv/en) — ifyllda och publicerade för de fyra utvalda uppdragen. OBS: utfallsrutorna är markerade "siffra saknas" tills faktiska siffror fylls i; Studion behöver deployas om för de nya fälten. - "Uppdrag" tillagd i huvudnavigationen; sidan ingår i sitemap och prerender (128 rutter) med ItemList-JSON-LD.
- Assignment-schemat utökat med
- Ny sektion: Ordlista (
/ordlista+/en/ordlista) — 16 tvåspråkiga "Vad är …?"-sidor om plattformsteknik, DevOps, DX och modern mjukvaruleverans (golden path, DORA, GitOps, SRE, MCP m.fl.).- Ny Sanity-typ
glossaryTermmed term, kort definition, brödtext samt relaterade tjänster och begrepp (svaga referenser). Studion behöver deployas om för att typen ska synas i redigeringsgränssnittet. - Varje sida har DefinedTerm-JSON-LD, hreflang (sv/en/x-default) och länkar vidare till tjänstesidor och blogginlägg; sidorna ingår i sitemap och prerender (126 rutter totalt).
- Ordlistan länkas från footern på alla sidor.
- Ny Sanity-typ
- SEO-fixar, audit punkt 6–8:
- Nya sökordsrika sidtitlar: tjänstesidorna får ett nytt
seoTitle-fält i Sanity (sv/en, ifyllt och publicerat för alla sex tjänster, t.ex. ”DevOps-konsulter — CI/CD, drift & incidenter”), och sektionssidorna (konsulttjänster, konsulter, branscher, kontakt, anteckningsbok) får seo-titlar via i18n./konsulttjansterheter inte längre ”Åtaganden” i sökresultat. - Ny 1200×630 og-bild (
/og-default.png) för länkdelningar; loggan kvar som Organization-logotyp i JSON-LD. Konsultsidornas meta-beskrivningar förlängda (tagline + introduktion). - Typsnitten self-hostas nu som variabla woff2 under
/fonts/med preload — inga anrop till fonts.googleapis.com på kritiska vägen. - OBS: Studion behöver deployas om för att
seoTitle-fältet ska synas i redigeringsgränssnittet.
- Nya sökordsrika sidtitlar: tjänstesidorna får ett nytt
- SEO-fixar efter fullständig audit (punkt 1–5 av 8):
- Startsidans hero-rubrik är nu sidans
<h1>(båda språken) — tidigare saknade startsidan H1 helt. - Okända URL:er får riktig 404-status: 404-sidan prerendras till
404.html, och SPA-fallbacken pekar på ett neutralt skal (_shell.html) i stället för startsidans snapshot — inga fler soft-404:or med startsidans canonical. - Policysidorna (
/policy/*, sv + en) prerendras och ingår i sitemapen — tidigare fick crawlers bara startsidans skal. - Sanity-bilder optimeras via CDN-parametrar (
auto=format&fit=max&w=…&q=75→ WebP/AVIF, nedskalning) medfetchpriority="high"på herobilder ochloading="lazy"under fold. - Hashade assets under
/assets/cachas nuimmutablei ett år (tidigaremax-age=0).
- Startsidans hero-rubrik är nu sidans
- Engelska har nu egna URL:er under
/en/(t.ex./en/kontakt) i stället för att renderas på samma URL:er som svenskan. Svenska URL:er är oförändrade och förblir huvudspråk (x-default).- Språket styrs av URL:en — localStorage/navigator-detektering borttagen, så sökmotorer och besökare ser samma innehåll för en given URL.
- Alla tvåspråkiga sidor deklarerar ömsesidig
hreflang(sv/en/x-default), språkspecifik canonical,og:locale:alternateoch<html lang>. - Sitemap listar båda språkvarianterna med
xhtml:link-alternates (och/kontaktsom tidigare saknades); prerendern renderar alla/en-rutter. - Blogginlägg är fortsatt enspråkiga: ingen
hreflang, canonical pekar alltid på inläggets språk-URL. Listsidan/anteckningsbokfinns även som/en/anteckningsbok. - Språkväxlaren i menyn navigerar nu till samma sida i det andra språket.
- Ny bloggpost publicerad: "Plattform som produkt: sluta bygga verktyg ingen vill använda" (
/anteckningsbok/plattform-som-produkt), kategori Plattformsteknik. - Lade till markdown-arbetskopia för den tidigare publicerade posten "Ersätta AWS Access Keys med IAM Roles Anywhere":
frontend/src/pages/changes.md.
The log is written in Swedish in the repo’s CHANGELOG.md and shown here as is.