<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>Felix Boers – Blog</title>
	<subtitle>Notizen und Gedanken zu Softwarearchitektur, Entwicklung und mehr.</subtitle>
	<link href="https://www.felix-boers.de/blog/feed.xml" rel="self" />
	<link href="https://www.felix-boers.de/blog/" />
	<updated>2026-05-08T00:00:00Z</updated>
	<id>https://www.felix-boers.de/blog/</id>
	<author>
		<name>Felix Boers</name>
	</author>
	<entry>
		<title>Mein Obsidian-System nach über 1000 Notizen</title>
		<link href="https://www.felix-boers.de/blog/mein-obsidian-system-nach-ueber-1000-notizen/" />
		<updated>2026-05-08T00:00:00Z</updated>
		<id>https://www.felix-boers.de/blog/mein-obsidian-system-nach-ueber-1000-notizen/</id>
		<content type="html">&lt;p&gt;Mein Obsidian-Vault ist mittlerweile über 1000 Notizen groß – Meeting-Protokolle,
Trainingspläne, Bewerbungen, gelesene Paper, halbfertige Gedanken. Damit das
trotzdem benutzbar bleibt, halte ich mich an ein paar einfache Regeln, die ich
hier kurz zeige.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.felix-boers.de/images/blog/obsidian-graph.png&quot; alt=&quot;Obsidian-Graph mit über 1000 verlinkten Notizen&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Ein Vault, fast ohne Ordner&lt;/h2&gt;
&lt;p&gt;Fast alle Notizen landen im selben Ordner: &lt;code&gt;Notes/&lt;/code&gt;. Kein &lt;code&gt;Arbeit/&lt;/code&gt;, kein
&lt;code&gt;Privat/&lt;/code&gt;, kein &lt;code&gt;Sport/&lt;/code&gt;. Themen-Ordner zwingen jede Notiz in genau eine
Schublade, aber die meisten Gedanken gehören eigentlich in mehrere. Statt
Ordnern bekommt jede Notiz im Frontmatter ein &lt;code&gt;categories&lt;/code&gt;-Feld, das auf eine
andere Notiz verlinkt:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;categories&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;[[Meetings]]&quot;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;2026-07-01&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;topics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Eine Notiz kann so auch mehrere Kategorien gleichzeitig tragen – ein
Gesprächsprotokoll ist gleichzeitig &lt;code&gt;[[Meetings]]&lt;/code&gt; und über das &lt;code&gt;org&lt;/code&gt;-Feld
einer bestimmten Organisation zugeordnet.&lt;/p&gt;
&lt;h2&gt;Kategorien statt Hierarchie, dargestellt mit Bases&lt;/h2&gt;
&lt;p&gt;Jede Kategorie ist selbst eine ganz normale Notiz (&lt;code&gt;Journals.md&lt;/code&gt;,
&lt;code&gt;Papers.md&lt;/code&gt;, &lt;code&gt;Evergreens.md&lt;/code&gt;, &lt;code&gt;Trainingsfokus.md&lt;/code&gt;, …), die per
&lt;a href=&quot;https://help.obsidian.md/bases&quot;&gt;Bases&lt;/a&gt; – Obsidians eingebauter
Tabellen-/Datenbank-Ansicht – alle Notizen mit dieser Kategorie live
auflistet:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; categories.contains(link(&quot;Categories&quot;))
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;!file.name.contains(&quot;Template&quot;)&#39;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;views&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; table
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Table
    &lt;span class=&quot;token key atrule&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; file.name
        &lt;span class=&quot;token key atrule&quot;&gt;direction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ASC&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Damit ist jede Kategorie automatisch eine gefilterte, sortierbare Übersicht,
ohne dass ich eine Index-Seite von Hand pflegen muss. Neue Kategorien lege ich
über eine eigene Vorlage an, die genau eine solche Base einbettet.&lt;/p&gt;
&lt;h2&gt;Vorlagen und Automatisierung mit Templater&lt;/h2&gt;
&lt;p&gt;Neue Notizen entstehen fast nie leer. &lt;a href=&quot;https://silentvoid13.github.io/Templater/&quot;&gt;Templater&lt;/a&gt;
füllt Frontmatter-Felder wie &lt;code&gt;created&lt;/code&gt; automatisch aus – bei manchen
Vorlagen benennt es die Datei nach dem Speichern sogar gleich passend um.
Aus der Meeting-Vorlage:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## 🎯 Purpose/Objective

## 📝 Notes
-

&amp;lt;%*
await tp.file.rename(tp.file.creation_date(&amp;quot;YYYY-MM-DD HHMM&amp;quot;) + &amp;quot; Meeting&amp;quot;);
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ich muss beim Anlegen also nicht mehr an Datum oder Dateiname denken – ich
schreibe direkt los.&lt;/p&gt;
&lt;h2&gt;Zettelkasten-IDs für flüchtige Gedanken&lt;/h2&gt;
&lt;p&gt;Für Notizen, bei denen ich beim Anlegen noch nicht weiß, was daraus wird,
gilt eine eigene Regel: Das &lt;a href=&quot;https://github.com/chrisgrieser/obsidian-zk-prefixer&quot;&gt;zk-prefixer&lt;/a&gt;-Plugin
vergibt automatisch einen Zeitstempel als Dateiname (&lt;code&gt;YYYY-MM-DD HHmm&lt;/code&gt;),
sobald ich eine neue &amp;quot;Unique Note&amp;quot; erstelle. Kein Titel, keine
Kategorisierungs-Entscheidung – nur ein Gedanke, schnell festgehalten.&lt;/p&gt;
&lt;p&gt;Reift so eine flüchtige Notiz zu etwas Eigenständigem heran, bekommt sie
einen echten Titel und die Kategorie &lt;code&gt;[[Evergreens]]&lt;/code&gt; – angelehnt an
&lt;a href=&quot;https://stephango.com/evergreen-notes&quot;&gt;Andy Matuschaks Konzept der Evergreen Notes&lt;/a&gt;:
Notizen, die ein Thema atomar und dauerhaft festhalten, statt nur ein
Gesprächsprotokoll zu sein.&lt;/p&gt;
&lt;h2&gt;Daily Notes als Eingangstür&lt;/h2&gt;
&lt;p&gt;Jeder Tag bekommt über das &lt;a href=&quot;https://github.com/liamcain/obsidian-calendar-plugin&quot;&gt;Calendar&lt;/a&gt;-Plugin
eine eigene Notiz mit Links zum Vor- und zum nächsten Tag sowie einer
eingebetteten Base, die alle Notizen zeigt, die an diesem Kalendertag
entstanden sind.&lt;/p&gt;
&lt;h2&gt;Die übrigen Plugins, die den Alltag tragen&lt;/h2&gt;
&lt;p&gt;Ein paar weitere Plugins, ohne die das System nicht so reibungslos liefe:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;obsidian-git&lt;/strong&gt; – das Vault ist selbst ein Git-Repo und committet sich automatisch, quasi als Backup mit Versionshistorie.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;dataview&lt;/strong&gt; – für Abfragen, die (noch) keine Base sind.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tag-wrangler&lt;/strong&gt; und &lt;strong&gt;note-refactor-obsidian&lt;/strong&gt; – Tags aufräumen und flüchtige Notizen in atomare Evergreens aufteilen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;darlal-switcher-plus&lt;/strong&gt; – schneller Sprung zwischen über 1000 Notizen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;obsidian-excalidraw-plugin&lt;/strong&gt;, &lt;strong&gt;drawio-obsidian&lt;/strong&gt;, &lt;strong&gt;obsidian-plantuml&lt;/strong&gt; – Skizzen und Diagramme direkt in Notizen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pdf-plus&lt;/strong&gt; – Paper annotieren, ohne die PDF zu verlassen.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kein Obsidian-Plugin, aber genauso wichtig: &lt;a href=&quot;https://syncthing.net/&quot;&gt;Syncthing&lt;/a&gt;
hält das Vault zwischen Laptop, Desktop und Handy synchron – direkt
Geräte-zu-Geräte, ohne Cloud-Anbieter dazwischen.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.felix-boers.de/images/blog/syncthing-status-wiki.png&quot; alt=&quot;Syncthing-Status meines Vaults&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Vom Notiz zum Blogpost&lt;/h2&gt;
&lt;p&gt;Auch dieser Blog fängt in Obsidian an: Eine Notiz mit Kategorie
&lt;code&gt;[[Blog Idee]]&lt;/code&gt; trägt als Titel schon die Arbeitsüberschrift, dazu ein
&lt;code&gt;status&lt;/code&gt;-Feld (Idee → im Schreiben → veröffentlicht) und ein leeres
&lt;code&gt;channels&lt;/code&gt;-Feld für später, falls aus einem Post noch Social- oder
Video-Content wird. Der eigentliche Text entsteht aber nicht in Obsidian,
sondern direkt hier im Repo als Markdown – ein Copy-Paste-Schritt weniger ist
ein Schreib-Widerstand weniger. Dieser Post hier war so eine Notiz.&lt;/p&gt;
</content>
		<summary>Ein Blick in mein Obsidian-Vault: ein flaches Notizsystem ganz ohne Themen-Ordner, Kategorien statt Hierarchie, Zettelkasten-IDs für flüchtige Gedanken – und die Plugins, die das Ganze zusammenhalten.</summary>
	</entry>
	<entry>
		<title>Wie diese Website gebaut, getestet und veröffentlicht wird</title>
		<link href="https://www.felix-boers.de/blog/wie-diese-website-gebaut-getestet-und-veroeffentlicht-wird/" />
		<updated>2026-05-03T00:00:00Z</updated>
		<id>https://www.felix-boers.de/blog/wie-diese-website-gebaut-getestet-und-veroeffentlicht-wird/</id>
		<content type="html">&lt;p&gt;Diese Seite ist bewusst einfach gehalten: eine statisch generierte Website ohne
Backend und ohne Client-seitiges JavaScript (abgesehen von den üblichen
Drittanbieter-Skripten wie Google Tag Manager und Cookiebot). Hier ist ein
kurzer Überblick, wie das Ganze aufgebaut ist.&lt;/p&gt;
&lt;h2&gt;Templating: 11ty mit Nunjucks&lt;/h2&gt;
&lt;p&gt;Die Seiten sind einfache HTML-Dateien, die ein gemeinsames Layout erweitern.
&lt;a href=&quot;https://www.11ty.dev/&quot;&gt;11ty (Eleventy)&lt;/a&gt; übernimmt das Rendering, Nunjucks
liefert die Template-Syntax:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;{% extends &quot;layout.html&quot; %}
{% block title %}Blog – Felix Boers{% endblock %}
{% block content %}
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
{% endblock %}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das Layout definiert Blöcke für Titel, Meta-Tags, Open-Graph-Daten und den
eigentlichen Inhalt, sodass jede Seite nur überschreibt, was sie wirklich
braucht.&lt;/p&gt;
&lt;h2&gt;Styling: Tailwind v4 ganz ohne Config-Datei&lt;/h2&gt;
&lt;p&gt;Seit Version 4 konfiguriert man Tailwind direkt in CSS statt in einer
&lt;code&gt;tailwind.config.js&lt;/code&gt;. Die Design-Tokens dieser Seite (Farben, Schriftart)
stehen in einem &lt;code&gt;@theme&lt;/code&gt;-Block:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@theme&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;--color-accent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #4a9edd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;--color-surface&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #161f2e&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;--color-base&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #0d1117&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;--font-sans&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Montserrat&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ui-sans-serif&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; system-ui&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Diese Tokens tauchen dann als normale Utility-Klassen auf, z. B. &lt;code&gt;text-accent&lt;/code&gt;
oder &lt;code&gt;bg-surface&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Build: 11ty und Tailwind CLI Hand in Hand&lt;/h2&gt;
&lt;p&gt;Der Build besteht aus zwei unabhängigen Schritten – Tailwind kompiliert das
CSS, 11ty rendert die Seiten – beide schreiben in dasselbe &lt;code&gt;dist/&lt;/code&gt;-Verzeichnis:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rm -rf dist &amp;amp;&amp;amp; npm run build:css &amp;amp;&amp;amp; npm run build:eleventy&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;build:css&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tailwindcss -i src/styles/main.css -o dist/styles/main.css --minify&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;build:eleventy&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eleventy&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Tests: Playwright und ein selbstgebauter Kontrast-Check&lt;/h2&gt;
&lt;p&gt;Die Test-Suite läuft mit &lt;a href=&quot;https://playwright.dev/&quot;&gt;Playwright&lt;/a&gt; gegen einen
echten Produktions-Build. Neben Navigation, Links und Inhalten prüft ein
selbstgeschriebener WCAG-Kontrast-Test jeden sichtbaren Textknoten gegen seinen
tatsächlichen Hintergrund:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;contrast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; l1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;relLuminance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; l2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;relLuminance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; lighter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; darker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; l2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lighter &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.05&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;darker &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.05&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So fällt sofort auf, wenn eine neue Farbe (zum Beispiel für das
Syntax-Highlighting in diesem Blog) nicht genug Kontrast zum Hintergrund hat.&lt;/p&gt;
&lt;h2&gt;Deployment: Docker, Gitea Actions und semantic-release&lt;/h2&gt;
&lt;p&gt;Ein mehrstufiges Dockerfile baut die Seite und liefert sie über nginx aus:&lt;/p&gt;
&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; node:24-alpine &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; build&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;WORKDIR&lt;/span&gt; /app&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; . .&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; npm run build&lt;/span&gt;

&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; nginx&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; &lt;span class=&quot;token options&quot;&gt;&lt;span class=&quot;token property&quot;&gt;--from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;build&lt;/span&gt;&lt;/span&gt; /app/dist /usr/share/nginx/html&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jeder Push auf &lt;code&gt;main&lt;/code&gt; läuft durch Tests und Build; basierend auf
&lt;a href=&quot;https://www.conventionalcommits.org/&quot;&gt;Conventional Commits&lt;/a&gt; ermittelt
&lt;code&gt;semantic-release&lt;/code&gt; die nächste Version und setzt bei Bedarf einen Git-Tag.
Ein Tag-Push löst den Deploy-Workflow aus: Docker-Image bauen, in eine
eigene Registry pushen, per SSH auf dem Server den Container neu starten.
Ein vorgeschalteter Caddy-Reverse-Proxy kümmert sich um TLS und leitet
Anfragen an den Container weiter.&lt;/p&gt;
&lt;p&gt;Am Ende ist es ein sehr kleines, aber vollständiges System – und genau der
richtige Rahmen, um jetzt auch regelmäßiger zu bloggen.&lt;/p&gt;
</content>
		<summary>Ein Blick hinter die Kulissen dieser Seite: Templating mit Nunjucks, Styling mit Tailwind v4, automatisierte Tests mit Playwright und Deployment via Docker und Gitea Actions.</summary>
	</entry>
</feed>
