<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title># notACMS</title>
        <link>https://notacms.holas.pl/de/</link>
        <description><![CDATA[AI-friendly static site generator. Zero database. Pure Markdown.]]></description>
        <language>de</language>
        <atom:link href="https://notacms.holas.pl/de/feed/" rel="self" type="application/rss+xml"/>
                <lastBuildDate>Fri, 24 Apr 2026 00:00:00 +0000</lastBuildDate>
                        <item>
            <title><![CDATA[notACMS 1.1.0 — Schlanker Kern, Demo-Theme, freie Wahl]]></title>
            <link>https://notacms.holas.pl/de/beitraege/release-1-1-0/</link>
            <guid isPermaLink="true">https://notacms.holas.pl/de/beitraege/release-1-1-0/</guid>
                        <pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate>
                        <description><![CDATA[Zwei Themes, eine Entscheidung beim ersten Build Die wichtigste Änderung in 1.1.0: notACMS liefert jetzt zwei Themes ab Werk, und du wählst beim allerersten Build eines davon aus: ./notACMS deploy --demo # Standard — das Amber-Phosphor-Design, das du hier siehst ./notACMS deploy --bare # ein minimales Wireframe: Systemschriften, Light Mode, ~200 Zeilen CSS ddev build unterstützt dieselben Flags. E…]]></description>
            <content:encoded><![CDATA[<h2>Zwei Themes, eine Entscheidung beim ersten Build<a id="zwei-themes-eine-entscheidung-beim-ersten-build" href="#zwei-themes-eine-entscheidung-beim-ersten-build" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Die wichtigste Änderung in 1.1.0: notACMS liefert jetzt zwei Themes ab Werk, und du wählst beim allerersten Build eines davon aus:</p>
<pre><code class="language-bash">./notACMS deploy --demo    # Standard — das Amber-Phosphor-Design, das du hier siehst
./notACMS deploy --bare    # ein minimales Wireframe: Systemschriften, Light Mode, ~200 Zeilen CSS
</code></pre>
<p><code>ddev build</code> unterstützt dieselben Flags. Egal, welches du wählst — alle Funktionen laufen: mehrsprachige Inhalte, Blog, RSS, Sitemap, Suche, Kontaktformular, Bilder mit responsiven Varianten, Lesezeit, Lesefortschritt. Der Unterschied liegt nur in der Optik — und vor allem darin, wie viel du erbst, bevor du mit dem Anpassen beginnst.</p>
<h3>Schlanker Kern<a id="schlanker-kern" href="#schlanker-kern" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h3>
<p>Der Kern in <code>templates/</code>, <code>assets/</code>, <code>translations/</code> ist jetzt ein Wireframe. Er ist bewusst minimal gehalten, damit das Überschreiben eines einzelnen Blocks nicht gleich eine visuelle Sprache mitschleift, gegen die du ankämpfen musst. Wenn du ein maßgeschneidertes Design baust, starte mit dem Bare-Theme und du besitzt das gesamte Erscheinungsbild ab Tag eins.</p>
<h3>Demo-Theme<a id="demo-theme" href="#demo-theme" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h3>
<p>Das Demo lebt unter <code>docs/demo/</code> und wird nach <code>local/</code> kopiert, wenn du <code>--demo</code> wählst. Es ist das vollständige Amber-Phosphor-Design, das du gerade liest — Dark Mode, Such-Overlay, Docs-Sidebar, Theme-Umschalter, alles dabei. Starte hier, wenn du heute ein poliertes Design willst und planst, zu tweaken statt neu zu bauen.</p>
<h2>Das <code>local/</code>-Override-System<a id="das-local-override-system" href="#das-local-override-system" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Beide Themes nutzen denselben Mechanismus: Jede Datei in <code>local/</code> hat Vorrang vor dem entsprechenden Pfad im Kern.</p>
<table>
<thead>
<tr>
<th>Schicht</th>
<th>Override-Ort</th>
<th>Resolver</th>
</tr>
</thead>
<tbody>
<tr>
<td>Twig-Templates</td>
<td><code>local/templates/*.html.twig</code></td>
<td>Symfony-Kernel</td>
</tr>
<tr>
<td>SCSS-Entrypoint</td>
<td><code>local/assets/styles/app_local.scss</code></td>
<td>Sass-Bundle</td>
</tr>
<tr>
<td>JS-Entrypoint</td>
<td><code>local/assets/app.js</code></td>
<td>AssetMapper-Importmap</td>
</tr>
<tr>
<td>Übersetzungen</td>
<td><code>local/translations/messages.*.yaml</code></td>
<td>Symfony-Translator</td>
</tr>
<tr>
<td>Inhalte</td>
<td><code>local/content/**</code></td>
<td>Parameter <code>notacms_content</code></td>
</tr>
<tr>
<td>Nginx-Snippets</td>
<td><code>local/docker/nginx/*.conf</code></td>
<td>Container-Entrypoint</td>
</tr>
</tbody>
</table>
<p>Der Kern wird nie bearbeitet. <code>git pull</code> bleibt sauber. Anpassungen leben im Repo deiner Site, nicht in einem Fork dieses Repos.</p>
<h2>Upgrade von 1.0.0<a id="upgrade-von-100" href="#upgrade-von-100" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Wenn du 1.0.0 benutzt hast und deine Site exakt so aussehen soll wie vorher, ist das Kompatibilitätspaket ein Einzeiler:</p>
<pre><code class="language-bash">cp -r docs/customization/old-template/. local/
ddev build
</code></pre>
<p>Das legt das komplette Theme vor 1.1.0 — Templates, SCSS, Schriften, Bilder, Übersetzungen — in <code>local/</code> ab. Deine Site rendert exakt wie zuvor. Anschließend kannst du Dateien aus <code>local/</code> selektiv entfernen, sobald du neue Design-Elemente übernimmst.</p>
<p>Die echten Breaking Changes, auf die du stößt, wenn du den alten Kern angepasst hast:</p>
<ul>
<li><strong>SCSS-Entrypoint umbenannt</strong>: <code>local/assets/styles/local.scss</code> → <code>local/assets/styles/app_local.scss</code>. Benenne die Datei um und passe den Import in <code>local/assets/app.js</code> an.</li>
<li><strong>SCSS-Farbvariablen im Kern durch CSS Custom Properties ersetzt</strong>: <code>$color-body</code> → <code>var(--text)</code>, <code>$color-link</code> → <code>var(--accent)</code> usw. Vollständige Zuordnung in <a rel="nofollow noopener noreferrer" target="_blank" href="https://github.com/holas1337/notACMS/blob/main/UPGRADE-1.1.md">UPGRADE-1.1.md</a>.</li>
<li><strong>Übersetzungsschlüssel entfernt</strong> aus dem Kern (im Demo-Theme weiterhin vorhanden): <code>header.tagline</code>, <code>nav.projects</code>, <code>nav.search</code>, <code>blog.published_on</code>, <code>blog.comments_disabled</code>. Wenn deine Templates <code>'...'|trans</code> auf diese Schlüssel aufrufen, passe das an.</li>
<li><strong>Verzeichnis <code>docs/examples/</code> entfernt</strong>: Die nützlichen Teile sind nach <code>docs/customization/old-template/</code> umgezogen; die Scratch-Override-Beispiele wurden durch das Bare/Demo-Modell abgelöst.</li>
</ul>
<p>Siehe <a rel="nofollow noopener noreferrer" target="_blank" href="https://github.com/holas1337/notACMS/blob/main/UPGRADE-1.1.md">UPGRADE-1.1.md</a> für die vollständige Liste mit Vorher/Nachher-Snippets.</p>
<h2>Ebenfalls neu in 1.1.0<a id="ebenfalls-neu-in-110" href="#ebenfalls-neu-in-110" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<ul>
<li><strong>Lesezeit</strong> und <strong>Lesefortschritt</strong> auf Posts, Docs und Releases.</li>
<li><strong>Sprachumschalter</strong> als Twig-Extension (<code>lang_switch_urls</code>) mit korrekten Fallback-Ketten für Archive, paginierte Listen und Startseiten.</li>
<li><strong>Post-Excerpts entfernen Überschrift-Anker</strong> — keine verirrten <code>#</code>-Zeichen mehr in den Listenkarten.</li>
<li><strong>Test-Suite-Gerüst</strong> unter <code>tests/Unit/</code>, <code>tests/Integration/</code>, <code>tests/Fixtures/</code> mit initialer Abdeckung und einem vom Host ausführbaren <code>test</code>-Befehl.</li>
<li><strong>KI-Agent-Skills</strong> unter <code>.claude/skills/</code> für die Arbeit am Repo: Locales hinzufügen, Doc-Alignment-Checks, Site-Sweeps, Übersetzungen und Erstellen von Upgrade-Guides.</li>
</ul>
<h2>Vollständiges Changelog<a id="vollständiges-changelog" href="#vollständiges-changelog" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Jede Änderung mit Kategorie: <a rel="nofollow noopener noreferrer" target="_blank" href="https://github.com/holas1337/notACMS/blob/main/CHANGELOG.md#110---2026-04-24">CHANGELOG.md</a>.</p>
]]></content:encoded>
                                    <category><![CDATA[releases]]></category>
                                    <category><![CDATA[release]]></category>
                        <category><![CDATA[announcement]]></category>
                    </item>
                <item>
            <title><![CDATA[notACMS v1.0.0]]></title>
            <link>https://notacms.holas.pl/de/beitraege/release-1-0-0/</link>
            <guid isPermaLink="true">https://notacms.holas.pl/de/beitraege/release-1-0-0/</guid>
                        <pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate>
                        <description><![CDATA[Was in v1.0.0 steckt Nach mehreren Monaten internem Einsatz in persönlichen Projekten markiere ich das erste stabile Release. Der Kern-Funktionsumfang ist solide genug, um damit echte Seiten zu bauen. Content-Pipeline Die Content-Pipeline ist das Herzstück von notACMS. Sie liest das local/content/-Verzeichnis, parst Frontmatter und generiert mit einem einzigen Befehl eine vollständige statische Se…]]></description>
            <content:encoded><![CDATA[<h2>Was in v1.0.0 steckt<a id="was-in-v100-steckt" href="#was-in-v100-steckt" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Nach mehreren Monaten internem Einsatz in persönlichen Projekten markiere ich das erste stabile Release. Der Kern-Funktionsumfang ist solide genug, um damit echte Seiten zu bauen.</p>
<h3>Content-Pipeline<a id="content-pipeline" href="#content-pipeline" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h3>
<p>Die Content-Pipeline ist das Herzstück von notACMS. Sie liest das <code>local/content/</code>-Verzeichnis, parst Frontmatter und generiert mit einem einzigen Befehl eine vollständige statische Seite.</p>
<ul>
<li>Markdown-Inhalte mit YAML-Frontmatter</li>
<li>CommonMark-Rendering mit Überschriften-Permalinks</li>
<li>Excerpt-Generierung aus Fließtext</li>
<li>Berechnung der Lesezeit</li>
</ul>
<h3>Mehrsprachiges Routing<a id="mehrsprachiges-routing" href="#mehrsprachiges-routing" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h3>
<p>Locales werden in <code>_site.yaml</code> definiert. Jede Locale erhält ihren eigenen URL-Raum, mit optionalen Pfadüberschreibungen in <code>_routes.yaml</code>. <code>hreflang</code>-Tags werden automatisch generiert.</p>
<pre><code class="language-yaml">locales:
  en:
    label: &quot;English&quot;
    date_format: &quot;M d, Y&quot;
  pl:
    label: &quot;Polski&quot;
    date_format: &quot;d.m.Y&quot;
</code></pre>
<h3>Pagefind-Suche<a id="pagefind-suche" href="#pagefind-suche" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h3>
<p>Volltextsuche ist über <a rel="nofollow noopener noreferrer" target="_blank" href="https://pagefind.app/">Pagefind</a> in die statische Ausgabe eingebaut. Der Build-Befehl generiert den Suchindex automatisch. Keine externe API, keine serverseitige Suche — nur ein statischer Index, der auch offline funktioniert.</p>
<h3>Bildverarbeitung<a id="bildverarbeitung" href="#bildverarbeitung" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h3>
<p>Bilder, die sich neben den Inhalten befinden, werden beim Build verarbeitet. notACMS generiert WebP-Varianten in mehreren Breiten, aktualisiert <code>src</code>-Attribute automatisch mit responsivem <code>srcset</code> und übernimmt die Pfadzuordnung zwischen Inhalts- und Ausgabeverzeichnissen.</p>
<h3>DDEV lokale Entwicklung<a id="ddev-lokale-entwicklung" href="#ddev-lokale-entwicklung" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h3>
<p>Die Entwicklungsumgebung ist mit DDEV vollständig containerisiert. <code>ddev start</code> stellt PHP 8.5, Nginx und alle Build-Werkzeuge bereit. <code>ddev build</code> erzeugt die statische Ausgabe. <code>ddev code-check</code> führt PHPStan und PHP CS Fixer aus.</p>
<h2>Breaking Changes<a id="breaking-changes" href="#breaking-changes" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Dies ist das erste stabile Release. Wer eine Pre-1.0-Version verwendet hat: Das <code>_site.yaml</code>-Schema prüfen — der <code>social</code>-Schlüssel wurde von einer Liste in eine Map geändert.</p>
<h2>Upgrade<a id="upgrade" href="#upgrade" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<pre><code class="language-bash">git pull
ddev composer install
ddev build
</code></pre>
<h2>Was als nächstes kommt<a id="was-als-nächstes-kommt" href="#was-als-nächstes-kommt" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>v1.1.0 wird sich auf das Design-System und die Dokumentation konzentrieren. Diese Seite — gebaut mit notACMS — wird zur offiziellen Dokumentation und Design-Referenz.</p>
]]></content:encoded>
                                    <category><![CDATA[releases]]></category>
                                    <category><![CDATA[release]]></category>
                        <category><![CDATA[announcement]]></category>
                    </item>
                <item>
            <title><![CDATA[Warum ich notACMS gebaut habe]]></title>
            <link>https://notacms.holas.pl/de/beitraege/the-idea/</link>
            <guid isPermaLink="true">https://notacms.holas.pl/de/beitraege/the-idea/</guid>
                        <pubDate>Fri, 01 Nov 2024 00:00:00 +0000</pubDate>
                        <description><![CDATA[Ausführlichere Hintergrundgeschichte in meinem persönlichen Blog: I left WordPress. Das Problem, auf das ich immer wieder stieß Jedes PHP-Projekt, an dem ich arbeitete, brauchte irgendwann eine Website. Dokumentation, eine Landingpage, ein Blog — das Übliche. Und jedes Mal, wenn ich nach einem Tool griff, landete ich am selben Ort: einem Tool, das mich dazu brachte, wie es zu denken — nicht wie ei…]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>Ausführlichere Hintergrundgeschichte in meinem persönlichen Blog: <a rel="nofollow noopener noreferrer" target="_blank" href="https://holas.pl/blog/why-i-left-wordpress/">I left WordPress</a>.</p>
</blockquote>
<h2>Das Problem, auf das ich immer wieder stieß<a id="das-problem-auf-das-ich-immer-wieder-stieß" href="#das-problem-auf-das-ich-immer-wieder-stieß" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Jedes PHP-Projekt, an dem ich arbeitete, brauchte irgendwann eine Website. Dokumentation, eine Landingpage, ein Blog — das Übliche. Und jedes Mal, wenn ich nach einem Tool griff, landete ich am selben Ort: einem Tool, das mich dazu brachte, wie es zu denken — nicht wie ein PHP-Entwickler.</p>
<p>Hugo ist schnell, aber seine Template-Sprache ist fremd. Jekyll setzt Ruby voraus. WordPress hat die falsche Form für statische Inhalte. Next.js ist mächtig, verwandelt aber ein Markdown-Publishing-Problem in ein JavaScript-Bundler-Problem.</p>
<p>Ich dachte immer wieder: Ich kenne Symfony bereits. Ich kenne Twig bereits. Ich habe Composer bereits. Warum muss ich ein neues Ökosystem lernen, nur um Text zu veröffentlichen?</p>
<h2>Die Entscheidung gegen eine Datenbank<a id="die-entscheidung-gegen-eine-datenbank" href="#die-entscheidung-gegen-eine-datenbank" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Das Erste, was ich entschied: keine Datenbank. Nicht „Datenbank optional&quot; — gar keine Datenbank. Inhalte leben in Dateien. Der Build-Prozess liest Dateien. Die Ausgabe sind Dateien.</p>
<p>Das erzwingt eine gewisse Disziplin. Die Inhaltsstruktur muss explizit und vorhersehbar sein. Es gibt keine Datenbankabfrage, auf die man zurückgreifen kann, wenn man verwandte Beiträge finden oder eine Sitemap generieren möchte. Alles muss aus dem Dateibaum ableitbar sein.</p>
<p>Diese Einschränkung stellte sich als die richtige heraus. Sie macht das System leicht verständlich, einfach zu sichern und trivial für KI-Tools nutzbar.</p>
<h2>KI-freundlich by Design<a id="ki-freundlich-by-design" href="#ki-freundlich-by-design" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Ich begann darüber ernsthaft nachzudenken, als ich LLMs in meiner täglichen Arbeit einzusetzen begann. Eine KI um Hilfe beim Generieren von Inhalten, Übersetzen von Seiten oder Validieren von YAML-Schemas zu bitten, ist unkompliziert, wenn das Format Plain Text ist.</p>
<p>Bei einem datenbankgestützten CMS müsste man das Schema erklären, SQL schreiben und Migrationen verwalten. Mit notACMS übergibt man der KI ein Verzeichnis mit Markdown-Dateien, und sie kann Inhalte direkt lesen, generieren und bearbeiten — weil das Format einfach Text ist.</p>
<p>Das ist keine nachträglich hinzugefügte Funktion. Es ist der Grund, warum das System so gestaltet ist, wie es ist.</p>
<h2>Das Symfony-Fundament<a id="das-symfony-fundament" href="#das-symfony-fundament" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Ich habe notACMS auf Symfony 7 aufgebaut, aus demselben Grund, warum ich Symfony für alles andere nutze: Es ist explizit, typisiert und gut dokumentiert. Der DI-Container, Konsolenbefehle, Twig — all das ist Standard-Symfony. An der Infrastruktur ist nichts Neuartiges.</p>
<p>Das Content-Modell ist der interessante Teil. Das Routing-System liest <code>_routes.yaml</code> und generiert Symfony-Routen aus dem Content-Baum. Der Build-Befehl rendert jede Route und schreibt statisches HTML. Die Service-Schicht ist schlank und austauschbar.</p>
<h2>Was als nächstes kommt<a id="was-als-nächstes-kommt" href="#was-als-nächstes-kommt" class="heading-anchor" aria-hidden="true" title="Permalink">#</a></h2>
<p>Dieses erste Release ist ein funktionierendes Fundament. Was ich noch bauen möchte:</p>
<ul>
<li>Pagefind-Suchintegration (kommt in v1.0.0)</li>
<li>Bessere Bild-Pipeline mit WebP-Generierung</li>
<li>Vollständigere mehrsprachige Unterstützung</li>
<li>Eine vollwertige Design-Referenz-Seite (dazu entwickelt sich diese Seite gerade)</li>
</ul>
<p>Das Repository ist öffentlich. Wer mitverfolgen oder beitragen möchte: der Link befindet sich in der Fußzeile.</p>
]]></content:encoded>
                                    <category><![CDATA[releases]]></category>
                                    <category><![CDATA[announcement]]></category>
                        <category><![CDATA[open-source]]></category>
                    </item>
            </channel>
</rss>
