Kapitel 2

Komponenten

Jeder Baustein mit einer klaren Aufgabe. Dieses Kapitel geht sie einzeln durch: was der Baustein tut, worauf er läuft, womit er spricht — und was passiert, wenn er ausfällt.

Cockpit

Das Cockpit ist die Arbeitsoberfläche der Winzerin. Es läuft unter cockpit.wein-online-verkaufen.de als SvelteKit-Anwendung mit adapter-node im Docker-Container. Angemeldet wird sich über die Medusa Admin API; danach arbeitet die Oberfläche als Single-Page-Anwendung weiter.

Das Cockpit ist auch die erste Station neuer Weingüter: Der Anmeldelink aus der Registrierung führt nach /onboarding, wo Stammdaten und Passwort entstehen. Bis ein Tarif gebucht ist, läuft das Cockpit als kostenloser Account gegen die Self-Service-API — Shop-Funktionen sind sichtbar, aber gesperrt. Unter /shop-einrichten folgen Tarifwahl, Stripe Checkout und die Live-Anzeige der Einrichtung.

Was darin verwaltet wird

  • Weinbuch — Produkte, Jahrgänge, Preise, Bestände, Artikelnummern
  • Bestellungen — Positionen, Kundendaten, Status, Rechnungs-PDF
  • Content — Beiträge, Lagen, Rebsorten, Winzer-Profil
  • Kunden, Einnahmen, Gutscheine — Kundschaft, Umsätze mit Export, ausgegebene Gutscheine
  • Einstellungen — Profil und Logo, Versand, Zahlungen, E-Mail, Benachrichtigungen, Medienpool, Rechtliches

Technische Besonderheiten

Rechnungs-PDFs entstehen im Cockpit selbst: Ein HTML-Template wird von Puppeteer in einem mitgelieferten Chromium gerendert. Deshalb ist das Cockpit-Image deutlich größer als ein reines Node-Image. Bild-Uploads laufen nicht direkt gegen MinIO, sondern über die Medusa-API — so gilt für Dateien dieselbe Authentifizierung wie für alles andere.

Storefronts

Pro Weingut läuft eine eigene Storefront in einem eigenen Container. Alle stammen aus demselben Template unter storefronts/template/ und unterscheiden sich in zwei Dingen: den Umgebungsvariablen des Mandanten und dem Branding.

Umgebungsvariablen pro Mandant
TENANT_BASE_URL=https://medusa.wein-online-verkaufen.de
TENANT_PUBLISHABLE_KEY=pk_…
TENANT_SALES_CHANNEL_ID=sc_…
TENANT_REGION_ID=reg_…
TENANT_SHOP_DOMAIN=<slug>.wein-online-verkaufen.de
TENANT_SHOP_NAME="Weingut <Name>"
TENANT_STRIPE_ACCOUNT_ID=acct_…

Die Seiten werden serverseitig gerendert — die erste Antwort enthält bereits das fertige HTML samt Produktdaten. Das ist für Suchmaschinen wichtig und macht den ersten Seitenaufbau schnell, auch auf dem Handy im Weinberg.

Was eine Storefront enthält

  • Startseite, Katalog mit Filtern, Produktdetailseite, Suche
  • Warenkorb, Checkout mit eingebettetem Stripe, Merkzettel
  • Content-Seiten: Winzer-Portrait, Lagen, Rebsorten, Beiträge
  • Gutschein-Kauf und Gutschein-Einlösung im Checkout
  • Rechtliches: Impressum, Datenschutz, Widerruf, Versand

Shops aus dem Self-Service laufen direkt aus dem Template-Image weinshop-storefront-template; die Provisioning-Pipeline startet für jedes Weingut einen Container storefront-<slug> mit dessen Umgebungsvariablen. Nur individuell gebaute Shops haben ein eigenes Verzeichnis unter storefronts/.

Self-Service-API

Die Self-Service-API unter self-service.wein-online-verkaufen.de ist das Rückgrat der Selbstbedienung: SvelteKit mit adapter-node, eine SQLite-Datenbank für die Weingüter, ihre Status und den Stand der Einrichtung. Sie verwaltet Accounts und Abos, versendet Anmeldelinks und Go-live-E-Mails und führt die Provisioning-Pipeline aus. Landingpage und Cockpit sprechen sie im Docker-Netz direkt an.

Wichtige Endpunkte
EndpunktZweck
POST /api/registerAccount anlegen, Anmeldelink verschicken
GET /api/me, PATCH /api/tenantProfil lesen, Stammdaten und Shop-Konfiguration speichern
POST /api/create-checkout-sessionStripe Checkout für das Abo starten
POST /api/checkout/confirmZahlung nach der Rückkehr aus Stripe bestätigen, Einrichtung starten
POST /api/stripe/webhookAbschluss, Änderung und Kündigung des Abos von Stripe empfangen
GET /api/me/provisioning-statusFortschritt der Einrichtung für die Anzeige im Cockpit
POST /api/tenants/[id]/provisionEinrichtung erneut anstoßen (nur Betreiber, Admin-Schlüssel)
PUT /api/tenants/[id]/suspend, /unsuspendShop sperren und reaktivieren (nur Betreiber)
GET /api/shop-statusIst der Shop gesperrt? — abgefragt von Storefront und Cockpit

Provisioning-Pipeline

Die Pipeline macht aus einer bestätigten Zahlung einen laufenden Shop. Sie läuft im Hintergrund der Self-Service-API und arbeitet ihre Schritte der Reihe nach ab: Medusa-Login, Publishable Key, Cockpit-Benutzer, Sales Channel, Lager und Versand, Cockpit-Stammdaten, MinIO-Bucket, Stripe-Connect-Konto, Storefront-Container, Traefik-Route, Umami-Website und Go-live-E-Mail.

  • Geprüft — jeder Schritt hat eine eigene Prüfung, etwa ob der Sales Channel über die Store API wirklich Produkte ausliefert oder ob der Shop unter seiner Adresse antwortet
  • Rückrollbar — scheitert ein Pflichtschritt, werden er und alle vorherigen Schritte rückwärts entfernt
  • Einmalig — läuft oder lief die Einrichtung schon, startet sie nicht ein zweites Mal; der Betreiber kann einen gescheiterten Lauf gezielt wiederholen
  • Sichtbar — den Stand jedes Schritts fragt das Cockpit alle zwei Sekunden ab

Die einzelnen Schritte mit ihrer Bedeutung für das Weingut stehen im Onboarding-Kapitel.

Master Dashboard

Das Master Dashboard unter admin.wein-online-verkaufen.de ist die Oberfläche des Plattform-Betreibers — SvelteKit mit eigener SQLite-Datenbank für Interessenten, Feedback und Konfiguration. Die Daten der Weingüter holt es über die Self-Service-API.

  • Übersicht — Kennzahlen der Plattform
  • Kunden — Weingüter mit Stammdaten, vom kostenlosen Account bis zum laufenden Shop: Tarif, Status, Stand der Einrichtung; Notizen, Stammdaten, Sperren und Reaktivieren
  • Prospects — Anfragen aus dem Kontaktformular und Registrierte ohne Stammdaten
  • Feedback — Rückmeldungen aus den Cockpits, mit Antwort per E-Mail
  • Konfiguration — Plattform-Einstellungen wie Preise und Wartungshinweis

Anmelden dürfen nur Adressen aus der Betreiber-Liste ADMIN_EMAILS.

Medusa

Medusa v2 ist das Commerce-Backend und die einzige Komponente mit Datenbankzugriff. Es liefert Produkte, Varianten, Warenkörbe, Bestellungen, Kunden und Sales Channels — und darüber hinaus die Module, die diese Plattform zu einer Weinplattform machen.

Registrierte Module
ModulZweck
contentBeiträge, News und Termine des Weinguts
lageWeinbergslagen mit Bodenart, Exposition und Beschreibung
rebsorteRebsorten-Steckbriefe
winzerWinzer-Profil mit Historie, Team und Werten
product-reviewProduktbewertungen inklusive Aggregat
gift-cardGeschenkgutscheine mit Code-Einlösung und PDF
@medusajs/medusa/fileDatei-Ablage über den S3-Provider (MinIO)
@medusajs/medusa/paymentZahlungen über Stripe (Connect)

Jedes eigene Modul bringt Datenmodell, Service und API-Routen mit: Admin-Routen für das Cockpit, Store-Routen für die Storefronts. Die Store-Routen verlangen den Header x-publishable-api-key, über den die Mandantenzugehörigkeit aufgelöst wird.

PostgreSQL

Die Datenbank läuft im Image pgvector/pgvector:pg17. Die Vektor-Erweiterung wird derzeit nicht genutzt; das Image ist historisch gewachsen und schadet nicht. Hauptdatenbank ist medusa_db.

Wichtige Tabellen
TabellenInhalt
product, product_variant, product_optionWeine, Jahrgänge, Gebindegrößen
order, order_item, return, claimBestellwesen
customer, customer_groupKundschaft
sales_channelMandantengrenze
content_postBeiträge, News, Termine
lage, rebsorteLagen und Rebsorten
winzer, team_member, timeline_entry, winzer_valueWinzer-Profil
review, review_aggregateBewertungen
gift_card, gift_card_transactionGutscheine und ihre Einlösungen

Der Port ist nicht mehr auf dem Host geöffnet — die Datenbank ist ausschließlich aus dem internen Docker-Netz erreichbar. Gesichert wird nächtlich per pg_dump mit Ablage außerhalb des Servers.

Redis

Redis übernimmt zwei Aufgaben für Medusa: Es ist der Event-Bus, über den Subscriber wie die Bestellbestätigung oder die Lagerbestand-Warnung ausgelöst werden, und es hält die Sessions. Es läuft im alpine-Image, passwortgeschützt und gebunden an 127.0.0.1.

MinIO / S3

MinIO ist der Medienspeicher: Produktbilder, Content-Bilder und Logos liegen im Bucket medusa. Medusa spricht MinIO über das File-Modul mit S3-Provider an — es kennt also gar kein MinIO, sondern nur „ein S3“.

Ausgeliefert werden die Bilder unter s3.wein-online-verkaufen.de; die Verwaltungskonsole ist nur für den Betrieb gedacht. Jeder Self-Service-Shop bekommt bei der Einrichtung einen eigenen Bucket — öffentlich lesbar, aber nicht öffentlich beschreibbar. Weil die Schnittstelle S3-kompatibel ist, lässt sich der Speicher später ohne Codeänderung zu einem Cloud-Anbieter verschieben — nur die Zugangsdaten und der Endpunkt ändern sich.

Stripe

Bezahlt wird über Stripe, eingebettet direkt in den Checkout. Es gibt keine Weiterleitung auf eine fremde Seite — die Kundschaft bleibt im Shop des Weinguts.

Stripe Connect

Jedes Weingut hat sein eigenes Stripe-Konto, das über Stripe Connect mit der Plattform verbunden ist. Die Provisioning-Pipeline legt es bei der Einrichtung als Konto vom Typ Standard an; das Weingut schließt das Stripe-Onboarding — Identität und Bankverbindung — im Cockpit unter Einstellungen → Zahlungen ab. Es behält vollen Zugriff auf sein eigenes Stripe-Dashboard und sieht seine Auszahlungen selbst. Der Checkout bucht per Direct Charge auf dieses Konto; die Plattform behält nichts ein.

Davon getrennt nutzt die Self-Service-API Stripe für das Abo der Plattform: Stripe Checkout im Abo-Modus, Webhooks für Abschluss, Änderung und Kündigung.

Traefik

Traefik nimmt allen Verkehr an, leitet Port 80 auf 443 um, holt und erneuert die Let’s-Encrypt-Zertifikate und verteilt anhand des Hostnamens. Die Konfiguration kommt aus zwei Quellen: Docker-Labels an den Containern und statischen Dateirouten für alles, was nicht als Container läuft.

Für den Betrieb heißt das: Ein neuer Shop ist nach dem Start automatisch erreichbar und automatisch mit Zertifikat versorgt. Die Provisioning-Pipeline schreibt dafür eine Routendatei nach traefik/dynamic/; dank Wildcard-DNS für *.wein-online-verkaufen.de braucht es keinen DNS-Eintrag. Es gibt keinen Schritt „Proxy konfigurieren“.

Zusammenspiel

Wer den Stack von Hand hochfährt oder einen Ausfall einordnen will, braucht die Abhängigkeiten.

Startreihenfolge und Ausfallverhalten
DienstBrauchtVerhalten
PostgreSQL—Muss zuerst laufen. Ohne DB startet Medusa nicht.
Redis—Muss vor Medusa laufen (Event-Bus).
MinIO—Unabhängig. Fällt es aus, fehlen Bilder, der Shop läuft weiter.
MedusaPostgreSQL, Redis, MinIOHerzstück. Ohne Medusa zeigen Shops Fehlerzustände.
CockpitMedusa, Self-Service-APILogin läuft über Medusa; kostenlose Accounts und Tarifwahl über die Self-Service-API.
StorefrontsMedusaServerseitiges Rendering holt alle Daten aus der Store API.
Self-Service-APIMedusa, MinIO, Docker, StripeOhne sie keine Registrierung und keine neuen Shops — bestehende Shops laufen weiter.
Master DashboardSelf-Service-API, MedusaReine Betreiber-Oberfläche; fällt sie aus, merkt die Kundschaft nichts.
Traefik—Kann jederzeit laufen; erkennt neue Container und Routendateien automatisch.