White-Labeling mit gemeinsamer Codebasis
Mehrere Marken über eine einzige Hyvä-Codebasis auszuliefern, klingt einfach, solange es nur um ein anderes Logo geht. Sobald Farbpaletten, Schriftgroessen und ganze Abstandssysteme pro Marke variieren sollen, entscheidet die Wahl zwischen CSS-Variablen und separaten Tailwind-Configs darueber, wie wartbar das Setup in einem Jahr noch ist.
Inhaltsverzeichnis
- 1. Ausgangslage: mehrere Marken, eine Codebasis
- 2. CSS Custom Properties: Tailwind @theme mit var()-Referenzen
- 3. Separate Tailwind-Builds pro Marke
- 4. Trade-off: Laufzeitflexibilitaet gegen Build-Zeit-Optimierung
- 5. Wie das Theme-Fallback-System store-spezifisches CSS laedt
- 6. Asset-Austausch: Logo, Favicon und Social-Bilder pro Store-View
- 7. Tailwind-Safelist-Fallstricke bei dynamischen Brand-Klassen
- 8. Deployment-Workflow für mehrere Marken gleichzeitig
- 9. Langfristige Wartbarkeit: Design-Tokens dokumentieren
- 10. Zusammenfassung
- 11. FAQ
1. Ausgangslage: mehrere Marken, eine Codebasis
Während Magentos Fallback-Hierarchie und ViewModel-basierte Store-Erkennung regeln, welcher Layout-Inhalt und welche Übersetzung pro Store-View ausgeliefert werden, beantwortet das eine andere Frage nicht: Woher kommen die eigentlichen Design-Werte wie Markenfarbe, Akzentfarbe und Schriftgroesse, wenn zwei Marken auf demselben Theme-Code laufen sollen. Genau diese Design-Token-Ebene steht in diesem Artikel im Mittelpunkt, nicht die inhaltliche Store-Erkennung selbst.
Ein realistisches Szenario ist ein Betreiber, der unter zwei Store-Views zwei unterschiedliche Marken fuehrt, mit eigenem Logo, eigener Farbwelt und teils eigener Typografie, aber identischer Produktdatenbank und identischer Checkout-Logik. Ein kompletter Theme-Fork pro Marke wäre technisch möglich, fuehrt aber langfristig zu doppelt gepflegtem Code bei jeder Bugfix- oder Feature-Änderung.
2. CSS Custom Properties: Tailwind @theme mit var()-Referenzen
Tailwind CSS v4 im CSS-first-Ansatz definiert Design-Tokens direkt im @theme-Block als CSS Custom Properties. Statt feste Hex-Werte einzutragen, verweisen die Tailwind-Variablen auf allgemeine CSS-Variablen wie --brand-primary, deren tatsaechlicher Wert erst zur Laufzeit im Browser aufgeloest wird, abhaengig davon, welche Store-spezifische CSS-Datei zuletzt geladen wurde.
Der große Vorteil ist, dass ein einziger, kompilierter Tailwind-Build für alle Marken ausreicht, jede Utility-Klasse wie bg-brand-primary bleibt exakt gleich, nur der dahinterliegende Farbwert unterscheidet sich pro Store. Der Nachteil zeigt sich bei tiefgreifenden strukturellen Unterschieden, etwa wenn eine Marke grundsaetzlich größere Abstaende oder eine andere Schriftfamilie braucht, denn reine Farbwerte über CSS-Variablen zu steuern ist einfach, ganze Spacing-Skalen dagegen deutlich muehsamer.
/* web/tailwind/tailwind-source.css */
@theme {
--color-brand-primary: var(--store-brand-primary, #ea580c);
--color-brand-accent: var(--store-brand-accent, #fb8570);
}
/* web/css/store-brand-a.css, per Store-View über Layout-XML geladen */
:root {
--store-brand-primary: #0f4c81;
--store-brand-accent: #7fb2e5;
}
3. Separate Tailwind-Builds pro Marke
Die Alternative ist ein eigenstaendiger Tailwind-Build je Marke, jeweils mit eigenem @theme-Block und eigenem, fest kodierten Farb- und Abstandssystem, aber demselben zugrunde liegenden phtml-Template-Code. Hyväs hyva.config.json unterstützt mehrere Theme-Verzeichnisse innerhalb desselben Vendor-Namespaces, sodass sich pro Marke ein eigenes web/tailwind-Verzeichnis mit eigenem Build-Output anlegen lässt.
Dieser Ansatz eignet sich, sobald Marken sich nicht nur in Farben, sondern strukturell unterscheiden, etwa unterschiedliche Border-Radius-Werte, komplett andere Schriftgroessen-Skalen oder sogar unterschiedliche Grid-Systeme. Der Preis dafuer ist ein eigener Build-Prozess und eine eigene, ausgelieferte CSS-Datei pro Marke, was den Deployment-Workflow komplexer macht als eine einzelne, universelle CSS-Datei.
{
"themes": {
"Mironsoft/brand-a": {
"css-file": "tailwind/tailwind-source.css"
},
"Mironsoft/brand-b": {
"css-file": "tailwind/tailwind-source.css"
}
}
}
4. Trade-off: Laufzeitflexibilitaet gegen Build-Zeit-Optimierung
CSS-Variablen sind zur Laufzeit flexibel: Ein neuer Store mit einer neuen Akzentfarbe braucht lediglich eine neue, kleine CSS-Datei mit den passenden Custom Properties, kein neuer Tailwind-Build und kein neues Deployment der kompilierten Basis-Datei. Das macht diesen Ansatz ideal für Reseller-Modelle mit vielen, ähnlich strukturierten Marken, bei denen sich hauptsaechlich die Farbpalette unterscheidet.
Separate Configs bieten dagegen bessere Build-Zeit-Optimierung, weil Tailwinds Purge-Mechanismus pro Marke exakt nur die tatsaechlich genutzten Utility-Klassen in die finale CSS-Datei aufnimmt, ohne ungenutzte CSS-Variablen-Definitionen für Marken mitzuschleppen, die auf dieser Instanz gar nicht existieren. Bei nur zwei bis drei strukturell ähnlichen Marken ueberwiegt in der Praxis meist der Wartungsvorteil der CSS-Variablen-Lösung.
5. Wie das Theme-Fallback-System store-spezifisches CSS laedt
Die store-spezifische CSS-Datei mit den Custom-Property-Ueberschreibungen wird nicht hart im Basis-Template verlinkt, sondern über ein eigenes Layout-XML-Handle pro Store-View eingebunden, etwa default_storeview_brand_a.xml, das Magentos Fallback-Hierarchie automatisch nur für den passenden Store aufloest. So bleibt die Zuordnung von Marke zu Store-View deklarativ und ohne Code-Verzweigung im PHP oder im Template steuerbar.
Wichtig ist, die Store-spezifische CSS-Datei nach der kompilierten Tailwind-Basis-Datei zu laden, damit die Custom-Property-Ueberschreibungen tatsaechlich greifen und nicht durch die Standardwerte im @theme-Block ueberschrieben werden. Die Ladereihenfolge im head-Block entscheidet hier direkt darueber, ob das White-Labeling sichtbar wird oder nicht.
<!-- app/design/frontend/Mironsoft/default/Magento_Theme/layout/default_storeview_brand_a.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="css/store-brand-a.css"/>
</head>
</page>
6. Asset-Austausch: Logo, Favicon und Social-Bilder pro Store-View
Neben Farben gehoert der Austausch von Bild-Assets zum Kern jedes White-Labeling-Setups. Magentos Store-Design-Konfiguration erlaubt bereits im Adminbereich, Logo und Favicon pro Store-View unabhaengig zu setzen, ohne dass dafuer eigener Theme-Code nötig ist, solange das Logo-Template im Theme brav über $block->getLogoSrc() statt über einen hart kodierten Pfad arbeitet.
Für Social-Media-Vorschaubilder und weitere Meta-Assets, die nicht über die Standard-Store-Design-Konfiguration abgedeckt sind, bietet sich ein eigenes ViewModel an, das den aktuellen Store ermittelt und den passenden Asset-Pfad aus einer Konfigurations-Map zurueckgibt, statt diese Zuordnung über verstreute Bedingungen in mehreren Templates zu pflegen.
7. Tailwind-Safelist-Fallstricke bei dynamischen Brand-Klassen
Ein häufiger Fehler bei CSS-Variablen-basiertem Multi-Brand-Styling ist, Klassennamen dynamisch aus PHP oder JavaScript zusammenzusetzen, etwa 'bg-brand-' . $brandSlug. Tailwinds Purge-Prozess scannt Templates nur nach vollstaendigen, statischen Klassennamen und erkennt solche zusammengesetzten Strings nicht, wodurch die betroffene Utility-Klasse im finalen Build schlicht fehlt.
Die zuverlaessige Lösung ist, ausschliesslich vollstaendig ausgeschriebene Klassennamen wie bg-brand-primary zu verwenden und die eigentliche Markenunterscheidung komplett auf die Ebene der CSS-Variablen zu verlagern, nicht auf die Ebene der Klassennamen selbst. Damit bleibt der Purge-Scan zuverlaessig, unabhaengig davon, wie viele Marken später noch hinzukommen.
8. Deployment-Workflow für mehrere Marken gleichzeitig
Beim CSS-Variablen-Ansatz bleibt der Deploy-Ablauf unveraendert gegenueber einem Single-Brand-Setup: Ein Tailwind-Build, ein setup:static-content:deploy-Aufruf für alle Stores gemeinsam, die store-spezifischen CSS-Dateien mit den Custom-Property-Ueberschreibungen sind schlank genug, um ohne separate Build-Schritte direkt mit deployt zu werden.
Bei separaten Tailwind-Configs pro Marke braucht jede Marke einen eigenen Build-Durchlauf vor dem eigentlichen Static-Content-Deploy, und der Deploy-Befehl selbst muss pro Theme-Verzeichnis mit dem passenden -t-Flag aufgerufen werden. Das lässt sich gut automatisieren, sollte aber bewusst in CI-Skripten dokumentiert werden, damit bei neuen Marken kein Build-Schritt vergessen wird.
# Separate Configs: Build pro Marke, dann gemeinsamer Deploy
bin/npm --prefix app/design/frontend/Mironsoft/brand-a/web/tailwind run build
bin/npm --prefix app/design/frontend/Mironsoft/brand-b/web/tailwind run build
bin/magento setup:static-content:deploy de_DE -t Mironsoft/brand-a -f
bin/magento setup:static-content:deploy de_DE -t Mironsoft/brand-b -f
9. Langfristige Wartbarkeit: Design-Tokens dokumentieren
Je mehr Marken auf derselben Codebasis laufen, desto wichtiger wird eine zentrale Übersicht aller verfügbaren Design-Tokens, idealerweise als eigene Markdown-Datei oder Storybook-ähnliche Referenzseite, die dokumentiert, welche CSS-Variable welchen visuellen Zweck erfüllt. Ohne diese Dokumentation setzt jede neue Marke ihre eigenen, leicht abweichenden Variablennamen und die Konsistenz erodiert Schritt für Schritt.
Regressionsrisiko entsteht vor allem dort, wo ein gemeinsames Template unbeabsichtigt markenspezifische Annahmen enthält, etwa eine hart kodierte Farbe statt einer Variable in einem selten getesteten Randbereich wie der Fehlerseite. Ein kurzer visueller Regressionstest pro Marke bei jedem Theme-Release, selbst nur als Screenshot-Vergleich, faengt solche Fälle zuverlaessiger ab als eine rein manuelle Durchsicht.
| Ansatz | Build-Aufwand | Laufzeitflexibilitaet | Wartbarkeit | Empfehlung für |
|---|---|---|---|---|
| CSS Custom Properties | Gering, ein gemeinsamer Build | Hoch, neue Marke ohne neuen Build | Hoch bei aehnlicher Struktur | Viele, strukturell ähnliche Marken |
| Separate Tailwind-Configs | Hoch, ein Build pro Marke | Gering, Änderung braucht neuen Build | Mittel, mehr Dateien zu pflegen | Wenige Marken mit strukturellen Unterschieden |
| Kompletter Theme-Fork | Sehr hoch, unabhaengige Codebasen | Sehr hoch, völlig frei | Sehr gering, doppelte Pflege bei jedem Fix | Nur bei radikal unterschiedlichen Marken |
| Store-Design-Konfiguration (Assets) | Gering, Admin-Konfiguration | Hoch, sofort im Adminbereich aenderbar | Hoch, kein Code-Eingriff nötig | Logo, Favicon und einfache Asset-Wechsel |
Mironsoft
Hyvä-Theme-Entwicklung und Luma-Migration
Noch auf Luma unterwegs oder ein Hyvä-Theme, das nicht rund läuft?
Wir entwickeln Hyvä-Themes für Magento von Grund auf oder migrieren bestehende Luma-Shops sauber, mit Tailwind CSS, Alpine.js und ohne unnötiges JavaScript-Gepäck.
Luma-zu-Hyvä-Migration
Bestehenden Shop strukturiert und ohne Funktionsverlust auf Hyvä umstellen.
Custom-Theme-Entwicklung
Individuelles Hyvä-Theme nach Design-Vorgaben von Grund auf umsetzen.
Performance-Optimierung
Core Web Vitals und Ladezeiten im Hyvä-Frontend gezielt verbessern.
10. Zusammenfassung
White-Labeling in Hyvä
CSS-Variablen für Farbwelten
Tailwind @theme mit var()-Referenzen erlaubt neue Marken ohne neuen Build, solange sich hauptsaechlich Farben unterscheiden.
Separate Configs bei struktureller Abweichung
Sobald sich Abstaende, Schriftgroessen oder Grids grundlegend unterscheiden, lohnt sich ein eigener Tailwind-Build je Marke.
Ladereihenfolge entscheidet über Wirkung
Store-spezifisches CSS muss nach der kompilierten Basis-Datei geladen werden, sonst greifen die Custom-Property-Ueberschreibungen nicht.
Vollstaendige Klassennamen für sicheren Purge
Dynamisch zusammengesetzte Tailwind-Klassennamen werden vom Purge-Scan übersehen, Markenunterscheidung gehoert auf CSS-Variablen-Ebene.