Unser erstes npm-Paket: warum wir astro-split-domains teilen

6 Min. Lesezeit Read in English

Kurz gesagt

Wir haben unser Build-Skript als Open-Source-Paket veröffentlicht, weil die Lücke nicht nur uns betrifft: Astro kann statische Websites nicht von Haus aus auf mehrere Domains verteilen. Seit dem 11. Oktober 2026 liegt @codeaeffchen/astro-split-domains 0.1.0 auf npm, und unsere eigene Website bezieht es von dort. Erstes Ergebnis: 657 von 667 Dateien blieben byte-identisch, die übrigen 10 hatten einen Fehler, den wir erst beim Auslagern gefunden haben. Ob andere das Paket nutzen, lässt sich nach vier Tagen noch nicht sagen.

Am vergangenen Wochenende haben wir unser erstes npm-Paket veröffentlicht: @codeaeffchen/astro-split-domains. Es verteilt eine statische Astro-Website auf eine Domain je Sprache. Bei uns heißt das: Deutsch auf codeaeffchen.de, Englisch auf codeaeffchen.com, beides aus einem Build.

Wie das technisch funktioniert und worauf man bei zwei Domains achten muss, steht im Artikel Astro mehrsprachig: zwei Domains, zwei Sprachen, ein Build. Hier geht es um die andere Seite: warum wir ein internes Skript überhaupt veröffentlicht haben, was dabei Arbeit gemacht hat und was nach den ersten Tagen dabei herausgekommen ist.

Die Ausgangslage: ein Skript, das seit April lief

Seit April 2026 lag in unserem Repository eine Datei namens build-split.mjs. Sie baute die Website und teilte das Ergebnis danach in zwei Ordner auf, einen pro Domain. Am Ende waren es 225 Zeilen, und sie liefen bei jedem Deploy.

Das Skript war auf genau eine Website zugeschnitten. Die Domains standen fest im Code, der Name der Sitemap auch. Für die llms.txt gab es eine Sonderregel, weil jede Sprache ihre eigene Fassung hat. Das hat funktioniert, aber nur für uns, und nur, solange sich niemand fragte, warum Zeile 81 genau so aussieht.

Warum veröffentlichen statt liegen lassen

Die Lücke ist nicht unsere. Astro kann Sprachen zwar auf eigene Domains legen, die Option i18n.domains setzt laut Astro-Dokumentation aber eine Server-Ausgabe voraus. Wer eine rein statische Website hat, steht vor demselben Problem wie wir. Unsere Lösung lief ohnehin schon, also stellen wir sie zur Verfügung.

Öffentlicher Code muss sich erklären. Ein Skript im eigenen Repository darf Annahmen treffen, die nirgends stehen. Ein Paket, das andere einbinden, nicht. Diese Prüfung wollten wir für einen Teil unseres Builds, der bei jedem Deploy über 400 Seiten anfasst.

Wir nutzen es wie alle anderen. Unsere Website holt das Paket aus npm, nicht aus einem Ordner nebenan. Geht bei einem Update etwas kaputt, merken wir es bei unserem eigenen Deploy, bevor jemand anderes ein Issue schreiben muss.

Man sieht, wie wir arbeiten. Wer überlegt, uns ein Astro-Projekt zu geben, kann sich Code, Tests und Dokumentation ansehen, statt sich auf eine Referenzliste zu verlassen.

Was das Auslagern konkret bedeutet hat

Kopieren und hochladen hätte nicht gereicht. Die eigentliche Arbeit:

  • Optionen statt fester Werte. Domains, Sprachen, der Sitemap-Name und die Markierungen in der .htaccess sind jetzt Einstellungen. Unsere Sonderregel für die llms.txt wurde zur allgemeinen Option für Dateien, die jede Sprache selbst erzeugt.
  • Als Astro-Integration statt als Skript. Das alte Skript hat astro build selbst aufgerufen. Die Integration hängt sich in den Build ein und läuft danach. Eingebunden wird sie in der Astro-Konfiguration wie jede andere Integration.
  • Tests. 13 Tests decken Links, absolute Adressen, Sitemaps, robots.txt, Fehlerseite und .htaccess ab. Sie laufen bei jeder Änderung auf GitHub unter Node 20 und Node 22.
  • Keine eigenen Abhängigkeiten. Außer Astro selbst braucht das Paket nichts. Unser Sicherheits-Check der Abhängigkeiten fand nach dem Umstieg deshalb nichts Neues.
  • Grenzen in die Dokumentation. Das README sagt auch, was die Integration nicht tut: keine Seiten mit Server-Rendering, keine selbst erzeugten hreflang-Angaben, keine Adressen, die erst im Browser per JavaScript entstehen.
  • MIT-Lizenz. Jeder darf das Paket nutzen, auch in Kundenprojekten, ohne nachzufragen.

Am 11. Oktober ging Version 0.1.0 auf npm, am selben Morgen hat unsere Website umgestellt. Im Repository der Website sind dabei 232 Zeilen weggefallen und 45 dazugekommen.

Die Gegenprobe: 667 Dateien

Bevor die Website auf das Paket umgestellt hat, haben wir beide Wege gegeneinander laufen lassen: aus demselben Stand einmal mit dem alten Skript, einmal mit dem Paket. Beide erzeugten 667 Dateien. 657 davon waren byte-identisch.

Die übrigen 10 waren keine neuen Fehler, sondern alte. Es waren kleine Weiterleitungsseiten, die Astro für umgezogene Adressen erzeugt. Ihr Canonical zeigte bisher auf Adressen wie https://codeaeffchen.de/en/…, die es nach dem Aufteilen gar nicht gibt. Das alte Skript hatte diese Schreibweise übersehen, das Paket schreibt sie auf die englische Domain um.

Hätten wir das Skript nicht für andere aufbereitet, wäre uns das vermutlich nicht aufgefallen. Die Seiten sind auf noindex gesetzt und leiten sofort weiter. Gesehen hat den Fehler niemand, aber er stand in jedem Build.

Erste Ergebnisse nach vier Tagen

Stand 15. Oktober 2026, ehrlich aufgeschlüsselt:

  • npm: 465 Downloads, davon 398 am 11. und 67 am 12. Oktober. Die Zahl sagt wenig. Am 11. Oktober liefen unsere eigenen Pipelines rund 40-mal, weil wir an dem Tag viel geändert haben, und npm zählt außerdem automatische Spiegel und Scanner mit. Seit unsere Pipelines das Paket vermutlich aus ihrem Cache holen, zählt npm kaum noch Abrufe.
  • GitHub: keine Sterne, keine Issues, keine Forks. GitHub meldet 63 Klone von 34 verschiedenen Absendern zwischen dem 10. und 12. Oktober. Wer dahinter steht, zeigt GitHub nicht. Ein Teil davon sind die Testläufe des Pakets selbst.
  • Astro-Katalog: Über die Schlüsselwörter im package.json ist das Paket automatisch im Integrationsverzeichnis auf astro.build gelandet, dort noch mit dem Hinweis „new“.
  • Unsere Website: Jeder Deploy seit dem 11. Oktober läuft über das Paket, ohne Auffälligkeiten.

Nach außen gibt es also noch keinen Beleg, dass jemand anderes die Integration einsetzt. Das haben wir so erwartet: Das Paket löst ein Nischenproblem, und wer es braucht, sucht meist erst, wenn eine zweite Domain ansteht. Der greifbare Nutzen liegt bisher bei uns: weniger Code im eigenen Repository, Tests für einen kritischen Build-Schritt und ein behobener Fehler.

Wann sich das für eine kleine Firma lohnt

Wir würden es wieder so machen, aber nicht mit jedem Stück Code. Unsere Kriterien:

  1. Das Problem ist allgemein, nicht an einen Kunden oder ein Projekt gebunden.
  2. Der Code läuft schon produktiv, bei uns selbst. Wir veröffentlichen nichts, was wir nicht täglich nutzen.
  3. Er ist klein genug, um ihn zu pflegen. Das Paket hat 314 Zeilen Code. Das schaffen wir neben dem Tagesgeschäft.
  4. Kundencode bleibt Kundencode. Was wir für Kunden entwickeln, gehört ihnen. Veröffentlicht wird nur, was bei uns selbst entstanden ist.

Wer Code veröffentlicht, übernimmt eine kleine Verantwortung: Fragen beantworten, auf neue Astro-Versionen reagieren, Fehler beheben. Issues lesen wir, eine feste Antwortzeit versprechen wir aber nicht.

Wie es weitergeht

Version 0.1.0 heißt: Die Integration läuft bei uns stabil, die Optionen können sich aber noch ändern, wenn andere Websites andere Anforderungen mitbringen. Den Stand prüfen wir bei jedem größeren Astro-Update, weil unsere Website ihn als Erstes mitmacht.

Quellcode, Dokumentation und Issues liegen auf GitHub. Wie die Website drumherum aufgebaut ist, steht in der Case Study zu codeaeffchen.de.


Du willst eine statische Astro-Website auf mehreren Domains ausliefern, oder du hast eine Frage zur Integration? Schreib ein Issue auf GitHub, oder schreib uns direkt, wenn es um dein Projekt geht.

Häufige Fragen

Was macht @codeaeffchen/astro-split-domains?

Die Integration teilt einen statischen Astro-Build nach dem Bauen in einen Ordner je Domain auf, zum Beispiel Deutsch für example.de und Englisch für example.com. Dabei passt sie Links, Canonicals, hreflang-Adressen, Sitemaps, robots.txt, die Fehlerseite und optional die .htaccess an die jeweilige Domain an.

Darf ich das Paket kommerziell nutzen?

Ja. Es steht unter MIT-Lizenz und darf in eigenen und in Kundenprojekten eingesetzt, verändert und weitergegeben werden. Der Lizenzhinweis muss dabei erhalten bleiben.

Welche Voraussetzungen hat die Integration?

Astro ab Version 5 und Node.js ab Version 20, außerdem eine statische Ausgabe. Seiten, die bei jedem Aufruf auf dem Server entstehen, fasst die Integration nicht an. Weitere Abhängigkeiten hat das Paket nicht.

Was sagen die Downloadzahlen auf npm aus?

Wenig über echte Nutzer. npm zählt jeden Abruf aus der Registry, auch die eigenen Build-Pipelines und automatische Spiegel. Bei einem neuen Paket stammen die ersten Zahlen deshalb oft zum großen Teil vom Herausgeber selbst. Aussagekräftiger sind Issues, Pull Requests und abhängige Pakete.

Passende Projekte

Daniel Nilges
Daniel Nilges

Gründer & Full-Stack-Entwickler

20+ Jahre Erfahrung in der Webentwicklung. Spezialisiert auf Laravel, WordPress und individuelle Software für den Mittelstand.