detmans world
Projekte Fotografie Reiseberichte Wanderungen Über

Website Migration von Hugo zu Astro

5.1.2026 Kategorien: Digital

Meine Website, die nun über zehn Jahre mit Hugo betrieben wurde, habe ich auf Astro umgestellt.

Die Hugo-Website hat mir gute Dienste erwiesen; statisches Publishing bringt Sicherheit und wenig Wartungsaufwand, und die Flat-File-Organisation ist großartig im Zusammenspiel mit Fotos, die ich aus Lightroom heraus direkt in die Zielordner exportieren kann.

Gründe für den Wechsel

Hugo ist jedoch in Go geschrieben, einer Programmiersprache, die mir fremd ist – was die Möglichkeit, eigene Erweiterungen zu programmieren, deutlich einschränkt.

Zudem war mir der Layout-Mechanismus nicht mehr ganz klar; vielleicht habe ich ihn im Laufe der Zeit auch zerschossen. Die Hugo-Website basierte auf dem Caspar-Theme, und Erweiterungen – bei Hugo Shortcodes genannt – musste ich direkt im Layout vornehmen, weil die Suchpfade meine lokalen Shortcode-Libraries nicht gefunden haben.

Mit dem ständigen Ringen um die richtige Integration von Funktionen und Stylings in die Templates war auch meine Motivation gering, intelligentere Consent-Banner zu integrieren. Zu viel Mühe. Als die DSGVO-Abmahnwelle rollte, habe ich radikal alle externen Dienste (Komoot, YouTube, Maps, SoundCloud) deaktiviert – und so ist es dann auch über mehrere Jahre geblieben.

Auch das Diskussions-Plugin habe ich entfernt. In Hugo kam Disqus zum Einsatz, das später kommerzialisiert wurde; ich habe es daraufhin entfernt.

Strukturell wollte ich ebenfalls Veränderungen: Die Website adressiert nun mehr Themen rund um Fotografie, und ich wollte einen Bereich für fotografische Projekte und Sammlungen schaffen, die mit den Posts in Verbindung stehen.

Vorteile von Astro

Mit Astro habe ich inzwischen erste Erfahrungen gesammelt. Astro ist eine Node-Applikation, die – ähnlich wie Hugo – statische Seiten rendert, aber auch im hybriden Modus betrieben werden kann. Dadurch können Teile der Seite statisch sein, während andere dynamisch funktionieren.

Unterstützt wird das durch das in Astro sogenannte Islands-Konzept: Komponenten können mit beliebigen Frameworks (Svelte, Vite, React, Angular) umgesetzt werden – notfalls sogar nebeneinander auf derselben Seite.

Eine weitere Sache, die ich sehr schick finde: In Astro werden Styles und Skripte, die nur für bestimmte Funktionsbereiche gelten sollen, direkt in die jeweiligen Komponenten geschrieben und gelten dort lokal. Das erleichtert es, den Überblick über wachsende Style-Dateien zu behalten, die mit der Zeit immer mehr Altlasten sammeln, die nach Refaktorisierungen nicht mehr benötigt werden.

Vorgehensweise

Über drei Jahre hinweg habe ich ein großes Transformationsprojekt in der Versicherungsbranche begleitet. Ein wichtiges Teilprojekt war dabei die Migration, die immer wieder testweise durchgeführt wurde, bis alle Migrationsprobleme aufgelöst waren. In der Zwischenzeit kamen natürlich neue Daten hinzu.

Dieselbe Vorgehensweise habe ich auch hier angewendet: ein reproduzierbarer Migrationsprozess. Die Posts wurden mitsamt ihren Assets in die Astro-Verzeichnisstruktur übertragen, und es wurden automatische Anpassungen an der Markdown-Struktur vorgenommen:

  • die Frontmatter-Struktur wurde transformiert
  • alle Shortcodes wurden in Astro-Komponenten überführt

Vorgabe war, dass die URLs der Posts gleich bleiben, damit sich das SEO-Ranking nicht verschlechtert.

Auf dem Weg dorthin gab es natürlich viele Stolperfallen. Hugo war nicht so pingelig wie Astro. Fehlende Bilder mussten aufgelöst werden, die Formatierung von MathJax passte nicht überall, und site-interne Links hatte ich über die zehn Jahre hinweg mit verschiedenen Notationen angelegt.

Die Korrekturen habe ich im Source-Tree des Hugo-Systems vorgenommen und die Migration immer wieder erneut durchgeführt.

Design

Nach der erfolgreichen Übertragung ging es an das Design. Das Caspar-Theme bei Hugo gefiel mir gut, und ich habe mich daran orientiert. Die Entwicklung der Gestaltungslinie erfolgte gemeinsam mit ChatGPT, das mir dabei tatsächlich ein guter Design-Ratgeber war.

Ziel war ein reduziertes, typografisches Design, das zwei Dinge gut unterstützen sollte:

  • das Lesen der redaktionellen Texte
  • das Betrachten ausgewählter Fotos in Sammlungen und Projekten

In beiden Fällen ist ein schnörkelloses Design die beste Wahl. Beim Lesen von Texten und beim Betrachten von Bildern sollen keine Elemente stören. Inhaltliche Zugehörigkeiten und Abgrenzungen erfolgen daher ausschließlich über Schriftarten, -farben und Abstände – nicht über Trennlinien, Rahmen oder Farbflächen, die Unruhe erzeugen.

Die Schrift für den Lesetext – also für den redaktionellen Content – ist eine Serifenschrift, die durch eine Sans-Serif für Meta-Informationen ergänzt wird. Der Abschluss eines Textes erfolgt über eine einfache Sternchenleiste.

Auch das Design der neu hinzugekommenen Filterleisten für Posts habe ich so schlank wie möglich gehalten: Elemente lassen sich ein- und ausschalten, ohne Zusatzinformationen und ohne separates „Close“.

Programmierung mit ChatGPT

Die Umsetzung der Website und das Programmieren der Funktionen habe ich ebenfalls mit ChatGPT realisiert. Schritt für Schritt habe ich mir Skripte und Templates bauen lassen – ziemlich oldschool im Vergleich zu holistischen Ansätzen wie Cursor.

Die Probleme, die dadurch entstanden sind, waren Insellösungen und redundanter Code, den ich später mühsam auflösen musste.

Einerseits habe ich vom großen Kontextwissen von ChatGPT profitiert, sodass beispielsweise generierter CSS-Code häufig bereits sehr nah am Zieldesign lag. Andererseits war das interaktive Vorgehen als Arbeitsweise tief verankert: Anpassungen erfolgten lokal in Layout-Pages und Einzelkomponenten, anstatt systematisch in globalen Skripten.

Im Ergebnis habe ich eine funktionierende Website erhalten – allerdings mit sehr viel redundantem Code in den Komponenten.

Diesen Code in Script-Libraries und globale Style-Dateien zu überführen, hat einiges an Zeit gekostet, immer mit dem Risiko, beim nächsten Schritt etwas Wesentliches kaputt zu machen.

Problem Image Files

Ich habe in der Website sehr viele Fotos; ich exportiere diese direkt aus Lightroom, häufig in großen Formaten. um im Bedarfsfall alle Bildverarbeitungsprozesse möglichst verlustfrei durchführen zu können.

Astro übernimmt bei Verwendung des Astro-eigenen Image-Tags dabei die Konvertierung in die Zielformate, allerdings wird bei den Image-Tags als Fallback das Bild in der Originaldimension verwendet, welches auch nach Konvertierung zu webp immer noch zu groß ist.

Also hab ich das Rendering der Zielbilder selber gemacht, was die Bildgrößen deutlich reduziert hat.

Abschließend noch ein Entfernen der Originalbilder aus dem dist/_astro, dann kommen wir auf 1,3 GB.

DatenbereichDatengröße
Source Tree23 GB
dist29 GB
dist mit eigenem image-rendering5 GB
dist mit eigenem image-rendering, bereinigt1,3 GB

CDN Integration

Astro ist für den Betrieb von Assets in einem CDN vorbereitet; alle Bilder, CSS- und Javascript-Files sind gehasht und können somit lange gecacht werden -> eine neue Version wird über einen neuen Hash im Dateinamen identifiziert und erzwingt dadurch einen vollen Server-fetch.

Fazit

In Hugo hatte ich eine sehr schlanke Website; Anpassungen erfolgten überwiegend über Shortcodes. Insbesondere die Bildbehandlung hatte ich in einen eigenen Image-Shortcode ausgelagert, der automatisch optimierte Bildvarianten erzeugte.

In Astro gibt es dafür einen eigenen Asset-Mechanismus. Rückblickend hätte ich das Prerendering von Anfang an nutzen sollen. Stattdessen habe ich zunächst einiges an Aufwand in händische Lösungen gesteckt, um Bilder aus dem src-Tree in den public-Tree zu kopieren, nur um überhaupt Ergebnisse sehen zu können.

Der Slug-Mechanismus in Hugo ist sehr fehlertolerant und funktioniert ausgesprochen robust. In Astro ist der Slug zwar Teil des Frontmatters, kann aber nicht wie selbst definierte Frontmatter-Variablen programmatisch behandelt werden. Das wurde zum Problem, als ich Sonderfälle mit fehlenden Slugs abfangen musste.

In Hugo bot mir das Caspar-Theme ein klar strukturiertes Layout-Verzeichnis, in dem ich Anpassungen an Shortcodes und kleinere Fixes vorgenommen habe. In Astro verteilen sich Logik und Gestaltung hingegen auf mehrere Ebenen:

  • Routen wie pages/projekte/index.astro und pages/projekte/[slug].astro. Sie sind die primären Einstiegspunkte und können sowohl Logik als auch Layout enthalten oder weiter delegieren.
  • Layout-Astro-Dateien (bei mir ein Base- und ein Post-Layout), die sich technisch wie Komponenten verhalten.
  • Components als zentraler Baustein: von Einbindungen für Komoot, YouTube oder SoundCloud über Post- und Projekt-Teaser bis hin zu Consent-Banner, Filterleisten, Galerien und Teaser-Grids.
  • Libs mit TypeScript-Dateien, die Funktionslogik bündeln und von Routen und Komponenten trennen, um Redundanz zu vermeiden.

Wie man Code auf Komponenten, Layouts, Libs und Routen verteilt, entscheidet maßgeblich über die Wartbarkeit des Projekts. Obwohl es „nur“ ein Blog mit Posts – und inzwischen auch Projekten – ist, ist das Inventar in Astro deutlich umfangreicher geworden, als ich es mir ursprünglich gewünscht hätte.

Mehr Aufwand als erwartet hat auch die Finalisierung und der anschließende Cleanup verursacht, was allerdings weniger mit Astro selbst als mit der Umstellung insgesamt zu tun hat. Das betrifft insbesondere SEO-Daten, Social-Sharing-Integration (OG-Metadaten) und die Einbindung strukturierter Daten (JSON-LD).

Durch die Einführung von Projekten habe ich Bilder teilweise aus den Blogposts herausgelöst. Um zu vermeiden, dass sie ungenutzt im Source-Tree verbleiben, musste ich alle Verzeichnisse nach orphaned images durchsuchen und bereinigen. Dabei bestand immer die Gefahr, versehentlich zu viel zu löschen – sei es durch eigene Fehler oder fehlerhafte Skripte. Positiv daran war, dass ich in diesem Zuge auch Altlasten entfernen konnte: Fotos, die zwar in Post-Ordnern lagen, aber nie verwendet wurden.

Die manuelle Kontrolle nach jedem einzelnen Schritt war notwendig und zeitaufwändig, zumal der Astro-Buildprozess jeweils eine gewisse Zeit in Anspruch nimmt.

Kommentare

Lade Kommentare …


Formatierung möglich: **fett**, *kursiv*,`code`, Listen, Absätze.