01 — Profil · Making-of
So ist diese Seite gebaut
Eine kleine Website mit viel Sorgfalt im Detail: was darunter steckt, warum, und wie es geprüft wird.
01 Das Gerüst
SvelteKit mit Svelte 5, Tailwind CSS und TypeScript. Jede Seite wird beim Build vorgerendert und als fertiges HTML ausgeliefert, nur die 404-Seite entsteht erst bei der Anfrage. Davor steht ein kleiner Node-Server, der jeder Antwort ihre Sicherheits-Header mitgibt.
SvelteKit 2 · Svelte 5 · Tailwind 4 · TypeScript · Node 24
02 Gezeiten × Bento
Eine Höhenlinienkarte rund um Varel: Navy und Seeschaum, dazu ein einziges Orange als Signal. Auf der Startseite steht jede Linie für ein Jahr seit August 2018, berechnet aus drei Sinuswellen pro Ring, ohne Zufall und ohne Bibliothek. Meine Erfahrung ist ein Höhenprofil, von dem Lichio orange abzweigt.
Schibsted Grotesk · IBM Plex Mono · selbst gehostet
03 Hell, dunkel, Sonnenstand
„Auto“ folgt Sonnenauf- und -untergang in Varel, berechnet nach dem SunCalc-Algorithmus auf etwa eine Minute genau. Ein kleines Inline-Skript wählt das Farbschema, bevor das erste Pixel gemalt wird, damit nichts hell aufblitzt.
53°24′ N · 8°08′ O
04 Zwei Sprachen, eine Adresse
Deutsch und Englisch über Paraglide, ohne /en/ in der URL. Die Sprache folgt deiner Wahl, sonst Deutsch, und bewusst nicht der Browsersprache: Google crawlt aus den USA, und die Seite im Index soll so aussehen wie für Besucher aus Deutschland.
Paraglide · deine Wahl, sonst Deutsch
05 Sicherheit
Eine strenge Content Security Policy: Skripte, Schriften und Anfragen nur von dieser Domain, die zwei Inline-Skripte per SHA-256-Hash freigegeben. In jedem CI-Lauf lädt Chromium jede Seite und schlägt bei jedem Verstoß an. Dazu HSTS, COOP und eine Permissions-Policy, die Kamera, Mikrofon und Standort sperrt.
CSP 'self' · 2 Hashes · 0 Dritte
06 Barrierefreiheit
Jede Seite wird in jedem CI-Lauf mit axe gegen WCAG 2.2 AA geprüft, hell und dunkel: 0 Verstöße. Die Kontrast-Kachel im Profil misst ihre Farben live. Kleine Links sind mindestens 24 px hoch, der Fokus ist immer sichtbar, und wer weniger Bewegung möchte, sieht jede Animation gleich an ihrem Ende.
axe · WCAG 2.2 AA · hell und dunkel
07 Tempo
Fertiges HTML, die Schrift der Überschriften vorgeladen, kein nachträgliches Springen des Layouts. Seitenwechsel blenden per View Transitions über, und die Markierung in der Navigation gleitet mit. Wie schnell das bei echten Besuchen ist, steht live im Profil.
Vorgerendert · View Transitions · Web Vitals live
08 Statistik ohne Cookies
Umami läuft selbst gehostet auf demselben Server und wird über diese Domain ausgeliefert. Keine Cookies, keine gespeicherten IP-Adressen, also kein Banner. Gezählt werden Seitenaufrufe, Ladezeiten, Klicks nach draußen und jedes Moin. Der Schlüssel zur Statistik bleibt auf dem Server.
Umami · selbst gehostet · 0 Cookies
09 Ein Server, 1 GB
Ein Server bei Sliplane in Falkenstein. Auf 1 GB RAM laufen die Seite, Umami und dessen Postgres, der JavaScript-Heap der Seite ist auf 160 MB begrenzt. Jeder Push auf main baut ein Docker-Image, und der alte Container geht erst, wenn der neue gesund ist: Umschalten ohne Ausfall.
Sliplane · Falkenstein · Docker
10 Werkstatt
Renovate hält die Abhängigkeiten aktuell, exakt gepinnt und erst drei Tage nach einer Veröffentlichung. Vor jedem Commit laufen Prettier, svelte-check und ESLint. CI baut, prüft Typen und Barrierefreiheit, testet die CSP und baut das Docker-Image, alles in unter fünf Minuten.
Renovate · lefthook · GitHub Actions
11 Gefunden werden
Strukturierte Daten beschreiben die Seite, mich und Lichio, und das Profil ist als Profilseite markiert. Die Sitemap entsteht beim Build, mit dem Build-Datum als letzter Änderung. Impressum und Datenschutz stehen auf noindex und fehlen deshalb bewusst in der Sitemap.
JSON-LD · sitemap.xml · noindex für Rechtliches
12 Kleinigkeiten
Das Vorschaubild für geteilte Links rendert ein Skript aus denselben Farben, Texten und Höhenlinien wie die Seite, die Favicons entstehen in jeder Größe direkt aus der Tassen-Zeichnung. Die Tasse liegt auf einem 4-px-Raster, damit sie auch mit 16 px scharf bleibt. Und die 404-Seite zeigt die Karte gestrichelt: Nur diese Seite ist nicht drauf.
og-image.mjs · favicons.mjs