Tre webbplatser, ett litet system

Den här webbplatsen är caset. Konsultsidan, utvecklaranteckningarna och fotogalleriet är tre separata statiska webbplatser, byggda från ett repository och distribuerade som tre oberoende Cloudflare Pages-projekt. Det finns inget klientramverk, ingen databas och inget innehållshanteringssystem. Den enda serverkoden är en Worker som skickar kontaktformuläret via SMTP.

Uppdraget

Webbplatsen skulle vara snabb, läsbar och billig att hålla igång. Den skulle också rymma tre sorters arbete som inte hör ihop: kundkonsulting, personliga mjukvaruprojekt och fotografier. Navigering, typografi, metadata och sidfot skulle definieras en gång.

Den gamla sidan var redan byggd med Astro och ett delat paket, vilket var rätt instinkt. Det som behövde ändras var mängden maskineri runt omkring: webbtypsnitt från tredje part, ett lightbox-bibliotek från en CDN, scrollanimationer och en temaväxlare i JavaScript. Allt fungerade, men inget av det förtjänade sin plats på en sida vars uppgift är att bli läst.

Struktur

En npm-workspace innehåller fyra paket:

  • kit — delad layout, sidhuvud, sidfot, designtokens, typografi och sociala länkar;
  • runi.se — den tvåspråkiga konsultsidan;
  • dev.runi.se — projekt och anteckningar, på engelska;
  • photography.runi.se — galleriet.

Varje webbplats är ett eget Astro-projekt med egen site-URL, sitemap och byggutdata. Ändringar i kit påverkar alla tre; det som hör till en webbplats stannar där. Distributionerna är oberoende av varandra.

Varför inte en delad webbrot

En webbserver kan servera tre värdnamn från en katalog genom att skriva om varje förfrågan till en underkatalog per webbplats, med ett undantag för de delade _astro-tillgångarna. Det är en fin lösning, och den övervägdes.

Den valdes bort av tre skäl. Webbläsarcachar är partitionerade per toppdomän, så den delade CSS:en hämtas ändå igen på varje domän. Kanoniska URL:er, sitemaps och robots.txt blir specialfall per värd. Och ett enda fel i omskrivningen kan exponera en webbplats sidor under en annan domän. Delad källkod löser underhållet utan att dela runtime.

Innehåll som filer

Projekt och anteckningar är Markdown-filer med ett typat frontmatter-schema. Bygget misslyckas om ett fält saknas eller en kategori är felstavad, vilket är bättre än att upptäcka det i en webbläsare. Att lägga till ett projekt innebär att lägga till en fil och bygga om.

De engelska och svenska casen är separata filer med samma filnamn, så språkväxlaren alltid pekar på motsvarande sida. Integritetsinformationen är också Markdown. Fotogalleriet läser EXIF-data en gång vid bygget och skriver kamera, objektiv, bländare, slutartid och ISO i den statiska HTML:en — att lägga till ett foto innebär att lägga en fil i en mapp.

Nästan ingen JavaScript

Sidorna levererar inget ramverk och ingen klientkod. Två små skript finns:

  1. theme.js, en kort extern fil i dokumentets head som tillämpar ett sparat ljust/mörkt val före första renderingen;
  2. Cloudflare Turnstile, laddas endast på kontaktsidan;
  3. inget annat.

Temaväxlaren har två lägen: ljust och mörkt. Tills en besökare väljer följer sidan operativsystemets inställning. Valet sparas i localStorage; ingen kaka sätts. Skriptet är externt i stället för inline, vilket gör att Content Security Policy kan förbjuda inline-skript helt.

Kontaktformuläret postas till en Worker och omdirigerar till en statisk bekräftelsesida. Det fungerar utan JavaScript, förutom spamkontrollen.

Design

Paletten är Gruvbox Material, dämpad, i en ljus och en mörk variant. Typografin använder systemets serif för löptext, systemets sans för navigering och metadata och systemets mono för kod. Inga webbtypsnitt att ladda ner och ingen layoutförskjutning medan typsnittet laddas.

Layouten är en enda mätt kolumn med tunna linjer i stället för kort. Länkar är understrukna. Inga gradienter, skuggor, hovringslyft eller scrollanimationer. Ljust är standard; en maskin som ber om mörkt får mörkt.

Avvägningar

  • Publicering kräver ett ombygge. Det finns ingen redigerare i webbläsaren, vilket är en fördel för en sida av den här storleken och en begränsning för någon annan som skulle redigera den.
  • Det finns tre distributionsmål i stället för ett.
  • Kontaktformuläret kräver en Worker med utgående SMTP-åtkomst. Allt annat är statiska filer.
  • Turnstile gör kontaktformuläret beroende av JavaScript. Utan det skulle formuläret vara lättare att spamma.

Inget av detta har varit ett problem i praktiken. Det som togs bort — CMS:et, spårningen, UI-biblioteken från tredje part — var också det som krävde underhåll.

Byggt med

  • Astro
  • TypeScript
  • Cloudflare Pages
  • Cloudflare Workers
  • Cloudflare Turnstile
← Alla projekt