CMS Chronicle #01: Bygger bloggen på den rigtige måde den rigtige måde
Vi har bygget Artikler-sektionen på webhouse.dk denne uge. To gange. Den første version havde alt indkodet direkte i TSX. Den anden version gør det korrekt — indhold i CMS, rendering i koden.
Vi fanger os selv i et mønster igen og igen. Vi bygger noget, det virker, det ser rigtigt ud — og så opdager vi, at alt indholdet ligger direkte i komponentfilen. Denne uge opdagede vi det tidligt. To gange.
Hvad vi har bygget
Artikler-sektionen på webhouse.dk havde brug for en blog. Fire serier, hver med sin egen stemme og fokus:
- Field Notes — operationelle indsigter fra drift af produktionssystemer
- AI Dispatch — hvad vi lærer ved at bygge rigtige AI-værktøjer
- CMS Chronicle — denne serie, der følger byggeprocessen offentligt
- 30 Years — mønstergenkendelse over tre årtier med softwareudvikling
En kategoriside for hver. Individuelle artikel-sider. En fælles renderer. Det første AI Dispatch-indlæg — en artikel om, hvad der sker med designere, når AI overtager produktionen. Alt er live. Men vejen dertil havde en omvej.
Omvejen
Den første version af artikel-siden havde indholdet indkodet direkte i TSX-komponenten. Hvert afsnit, hvert citat, hver punktliste — JSX. Det så korrekt ud i browseren. Problemet er, at et website, der indkoder sit indhold direkte i sine komponenter, ikke rigtigt bruger et CMS. Det bruger et CMS til at styre nogle ting og foregiver, at resten ikke betyder noget.
Vi har en regel for dette. Den er skrevet ned. Alligevel ignorerede vi den.
“Regelen er enkel: Indhold lever i CMS. .tsx-filer indeholder renderingslogik, ikke tekst.”
Så omskrev vi det. Artikelens indhold er nu Markdown gemt i et content-felt i posts-samlingen. Strukturerede data — titel, uddrag, dato, kategori, sammenligningsblokken — lever som separate felter i JSON-dokumentet. TSX-filen modtager data og renderer det. Det er alt, den gør.
Sådan virker det i praksis
Vi bruger react-markdown med et tilpasset komponentkort. Hvert Markdown-element kortlægger til en stiliseret React-komponent:
- Afsnit og overskrifter renderes med læselig størrelse og korrekt mellemrum
- Citatblokke — blokcitationer, der starter med \u201c — får den store, fed skrift med en turkis venstre kant
- Statement-blokcitationer (alt andet) renderes som kompakte grønne prik-elementer, som disse
- Markøren
[comparison]i Markdown-strengen indsætter en struktureret Less/Mere-panels fra et separat JSON-felt
Sammenligningsblokken kan ikke udtrykkes i Markdown, så den lever side om side med indholdet som strukturerede data. Det er en lille konvention, der løser et reelt problem uden at overkomplicere modellen.
Hvad vi lærte
En regel, der ikke er i hukommelsen, er ikke en regel — det er et forslag. Princippet om "indhold lever i CMS" eksisterede i projektplanen, men ikke i den vedvarende hukommelsesfil, som Claude læser ved sessionens start. Så det blev ignoreret. Nu er det i hukommelsen.
Den anden ting: Playwright er nyttigt til at opdage renderingsfejl, man ellers ville gå glip af. Vi tog skærmbilleder af begge versioner side om side og kunne straks se, at blokcitat-fontstørrelserne, afsnitsmellemrummene og titelopdelingen alle var forkerte. At rette CSS ved at kigge på skærmbilleder er meget hurtigere end at rette det ved at læse kode.
Hvad kommer næste gang
CMS Chronicle-serien er det rigtige sted at dokumentere denne byggeproces offentligt. Hver session, der flytter noget meningsfuldt fremad, får et indlæg. Webstedet webhouse.dk og platformen @webhouse/cms bliver bygget parallelt — det ene tester det andet, og begge forbedres på grund af det.
Næste skridt: Fase 3. Supabase-adapter, PostgreSQL-backend, Docker-pakning og en Fly.io-deploy-pipeline. Når det lander, stopper @webhouse/cms med at være et lokal filsystem-værktøj og bliver noget, man rent faktisk kan køre i produktion.