2026-10-27 19:22:31 +01:00
2026-10-27 19:22:31 +01:00
2026-10-27 00:59:39 +01:00
2026-10-23 21:33:15 +02:00
2026-10-27 19:22:31 +01:00
2026-10-26 09:35:19 +01:00
2026-10-27 19:22:31 +01:00
2026-10-21 14:50:31 +02:00
2026-10-27 00:59:39 +01:00
2026-10-21 14:50:31 +02:00
2026-10-21 14:50:31 +02:00
2026-10-21 14:50:31 +02:00
2026-10-27 19:22:31 +01:00
2026-10-21 14:50:31 +02:00
2026-10-21 14:50:31 +02:00
2026-10-21 14:50:31 +02:00
2026-10-27 19:22:31 +01:00
2026-10-27 19:22:31 +01:00
2026-10-21 17:25:28 +02:00
2026-10-21 14:50:31 +02:00
2026-10-27 19:22:31 +01:00
2026-10-21 21:05:57 +02:00
2026-10-23 21:33:15 +02:00
2026-10-21 14:50:31 +02:00
2026-10-21 17:25:28 +02:00

Sendewerk

Sendewerk ist die redaktionelle Webanwendung für den Weg vom vorbereiteten Inhalt bis zur moderierten und archivierten Sendung. Der aktuelle Stand umfasst Etappe 1 bis 7: technisches Grundgerüst, Anmeldung und Rollen, Fundus, Sendungsbau, Live-Steuerung, Präsentationsausgabe, Abschluss, Archiv, Freigaben, RSS sowie technische REST- und MCP-Zugänge.

Voraussetzungen

  • Linux
  • Node.js 22.17 oder neuer (Node 24 LTS ist für das Cloudron-Image vorgesehen)
  • npm 10 oder neuer

Cloudron, Docker, eine Domain und externe Dienste sind für den lokalen Betrieb nicht erforderlich.

Frischer lokaler Start

npm ci
cp .env.example .env
SETUP_TOKEN="$(openssl rand -hex 32)"
sed -i "s/^SENDEWERK_SETUP_TOKEN=.*/SENDEWERK_SETUP_TOKEN=$SETUP_TOKEN/" .env
printf 'Betreiber-Setup-Token: %s\n' "$SETUP_TOKEN"
npm run setup
npm run dev

Danach ist die Anwendung unter http://localhost:5173 erreichbar. setup erstellt die konfigurierten Verzeichnisse, führt ausstehende Migrationen aus und lädt den reproduzierbaren Beispieldatensatz. Der Seed darf beliebig oft ausgeführt werden und ersetzt nur die von ihm verwalteten Beispieldaten.

Beim ersten Aufruf verlangt /setup den ausgegebenen Wert aus SENDEWERK_SETUP_TOKEN und legt genau einen Barkeeper an. Der Befehl schreibt den Wert in die nicht versionierte .env, damit auch spätere lokale Starts dieselbe Konfiguration verwenden. Nach erfolgreicher Einrichtung ist /setup dauerhaft geschlossen und der Token kann aus .env entfernt werden. Der Seed enthält bewusst kein Konto und kein Standardpasswort.

Konfiguration

Variable Vorgabe Bedeutung
SENDEWERK_DB_PATH .data/sendewerk.sqlite Pfad zur persistenten SQLite-Datei
SENDEWERK_UPLOAD_DIR .data/uploads Persistentes Upload-Verzeichnis
SENDEWERK_MAIL_OUTBOX_DIR .data/mail-outbox Lokale, nicht öffentlich ausgelieferte Testmail
BODY_SIZE_LIMIT 6M Requestlimit für private Bild-Uploads bis 5 MB
SENDEWERK_SETUP_TOKEN keine einmaliges Betreibergeheimnis, mindestens 32 Zeichen
SENDEWERK_APP_ORIGIN http://localhost:5173 feste Origin für Links und Cookie-Sicherheit
SENDEWERK_MAIL_TRANSPORT local local oder ausdrücklich smtp
SENDEWERK_MAIL_FROM lokaler Absender Absender; bei SMTP verpflichtend
SENDEWERK_SMTP_HOST keine SMTP-Server, nur im SMTP-Modus
SENDEWERK_SMTP_PORT 587 SMTP-Port
SENDEWERK_SMTP_SECURE false true für implizites TLS, üblicherweise Port 465
SENDEWERK_SMTP_USER keine optionaler SMTP-Benutzer
SENDEWERK_SMTP_PASSWORD keine optionales SMTP-Passwort
HOST adapterabhängig Bind-Adresse des Produktionsservers
PORT 3000 Port des Produktionsservers

Relative Sendewerk-Pfade werden vom Projektverzeichnis aus aufgelöst. In Cloudron liegen Datenbank und Uploads unter /app/data.

Eine öffentliche Produktions-Origin muss HTTPS verwenden. Nur für lokale Loopback-Adressen bleibt HTTP zulässig.

Der Vorgabemodus local baut keine Netzwerkverbindung auf. Einladungen und Passwort-Resets landen als JSON-Dateien in .data/mail-outbox; die enthaltenen Links sind Geheimnisse und dürfen nicht veröffentlicht werden. Echter Versand findet nur statt, wenn SENDEWERK_MAIL_TRANSPORT=smtp und die SMTP-Werte explizit gesetzt sind.

Inhalte und private Bilder

Neue Gedanken oder Links lassen sich im Eingang schnell erfassen. Im Fundus stehen leere Pieces sowie Vorlagen für Gespräch, Reaction/Fundstück und Interaktion bereit. Der Editor speichert Änderungen nach kurzer Pause automatisch; ein sichtbarer Status meldet Erfolg, Fehler oder eine parallele Änderung. In diesem Fall muss die Seite neu geladen werden, bevor erneut gespeichert wird.

Bereits gesendete Pieces und Pieces mit einer Einplanung in einer noch nicht abgeschlossenen Sendung sind standardmäßig ausgeblendet. Als gesendet gilt nur eine erledigte Verwendung in einer abgeschlossenen Sendung; übersprungene oder reservierte Inhalte gelten nicht als gesendet. Über Auch verwendete Inhalte zeigen und Auch eingeplante Inhalte zeigen lassen sich beide Gruppen unabhängig einblenden. Dann erscheinen auch Datum, Sendung und die aufklappbare Verwendungshistorie.

Markdown ist in Einleitung, Recherche, Moderation, Überleitung und Präsentation möglich. Die Ausgabe wird serverseitig auf eine begrenzte Auswahl sicherer Elemente und Links reduziert. Bilder dürfen höchstens 5 MB groß sein und müssen als JPEG, PNG, WebP oder GIF erkannt werden. Sie liegen im konfigurierten Uploadverzeichnis und sind nur über eine angemeldete Route erreichbar.

Für die Präsentation kann ein Piece alternativ genau eine seiner vorhandenen Quellen als Linkkarte oder Video verwenden. Linktitel, Anreißer und Bildadresse lassen sich manuell korrigieren. Vorschau laden ruft Metadaten ausdrücklich neu ab; manuell geänderte Felder werden dabei nicht überschrieben. Die Präsentation testen-Ansicht öffnet den aktuellen Piece-Inhalt isoliert und verändert weder eine Sendung noch deren laufende Ausgabe.

Sendungen planen

Unter Sendungen lässt sich ein neuer Stream leer, mit dem Standardablauf oder als Spieleabend anlegen. Abschnitte sind frei benennbar und können eine explizite Dauer erhalten; andernfalls ergibt sich ihre Dauer aus den eingeplanten Pieces. Die Reservebank zählt nie zur Planzeit.

Der sendefertige Fundus steht neben dem Ablauf. Pieces können mehrfach eingeplant und je Verwendung mit eigenem Titel, eigener Dauer und eigenen Redaktionstexten bearbeitet werden, ohne das Original zu verändern. Das Stift-Symbol öffnet dafür einen auch mobil scrollbaren Editor-Dialog. Aus Fundus aktualisieren übernimmt auf Wunsch Titel, Dauer und Redaktionstexte des aktuellen Originals; eigene Notizen, Live-Status und gemessene Zeiten bleiben erhalten. Abschnitte und Verwendungen lassen sich per Drag-and-drop sowie gleichwertig mit sichtbaren Schaltflächen und Auswahlfeldern verschieben. Twitch-Titel und Ankündigung sind kopierbar. Gleichzeitige Änderungen werden über die Revision der gesamten Sendung erkannt und nicht still überschrieben.

Die Quellspalte blendet gesendete und bereits in derselben Sendung eingeplante Originale zunächst aus; beide Gruppen lassen sich unabhängig wieder anzeigen. Eine konkrete Einplanung kann direkt hinter sich dupliziert werden. Dabei bleiben ihre angepassten Texte und ihre Dauer erhalten, während Live-Status und gemessene Zeiten neu beginnen. Piece duplizieren im Fundus erzeugt dagegen weiterhin einen eigenständigen Fundusinhalt.

Live moderieren und präsentieren

Die Live-Steuerung öffnet sich aus einer geplanten Sendung. Sie zeigt Einleitung, Moderationsstichpunkte und Überleitung in einstellbarer Prompter-Schrift; die private Recherche bleibt standardmäßig geschlossen. Zeiten und Ablaufleiste können ausgeblendet werden. Schriftgröße, Sichtbarkeit und Leseposition bleiben im Browser erhalten.

Start, Erledigen, Überspringen und Zurück werden persistent mit tatsächlichen Zeitintervallen gespeichert. Wiederholte Befehle erzeugen keine doppelte Zeitbuchung. Offene Pieces und die Reserve lassen sich während der Sendung sortieren beziehungsweise als nächster Beitrag einfügen.

Das separate Präsentationsfenster unter /heinzlive/... verwendet einen langen, widerrufbaren Zufallstoken. Es ändert sich ausschließlich durch die Aktion Präsentieren und erhält nur den bei der Einplanung gespeicherten Text-, Link- oder Video-Snapshot. YouTube- und TikTok-Adressen werden auf validierte IDs reduziert und ohne Autoplay in offiziellen Player-Iframes dargestellt. Andere oder unvollständige Videoquellen erscheinen als Linkkarte. Recherche, Moderationsnotizen, eigene Notizen, Kontodaten und interne Dateipfade werden weder im HTML noch im JSON-Zustand ausgeliefert. Der Token ist ein Zugangsgeheimnis und darf nicht weitergegeben oder protokolliert werden.

Metadaten und externe Vorschaubilder werden ausschließlich serverseitig mit DNS-, Redirect-, Zeit- und Größenlimits abgerufen. Private und lokale Netzwerkziele sind gesperrt. Eingebettetes HTML oder Skripte einer Quellseite werden nicht übernommen.

MCP und ChatGPT

Der lesende Streamable-HTTP-Endpunkt liegt unter /mcp. Seine konkrete Adresse ist die konfigurierte Anwendungs-Origin mit angehängtem Pfad:

https://<Cloudron-App-Domain>/mcp

Beispiel: Bei SENDEWERK_APP_ORIGIN=https://sendewerk.example.org lautet die MCP-URL https://sendewerk.example.org/mcp. Niemals einen technischen REST-Token an die URL hängen oder in ChatGPT eintragen. MCP verwendet einen eigenen OAuth-2.1-Flow mit Authorization Code, PKCE und kurzlebigen Tokens.

Die Verbindung stellt ausschließlich lesende Werkzeuge bereit:

  • get_profile identifiziert das verbundene Sendewerk-Konto ohne E-Mail-Adresse.
  • list_pieces und get_piece lesen Fundus-Pieces.
  • list_shows und get_show_rundown lesen Sendungen und deren Abläufe.

Die Detailwerkzeuge können private Recherche, Moderationsnotizen, Quellen, eigene Notizen und Reserveinhalte liefern. Der angemeldete Nutzer muss diesem Umfang ausdrücklich zustimmen. Sperrung oder Passwortwechsel widerrufen bestehende OAuth-Tokens; jede MCP-Anfrage prüft Konto, Scope, Ablauf und Zielressource erneut. MCP kann keine Inhalte schreiben.

In ChatGPT einrichten

  1. Zuerst Version 0.8.1 unter der endgültigen öffentlichen HTTPS-Origin bereitstellen. Lokalhost ohne öffentliches HTTPS ist für eine direkte ChatGPT-Verbindung nicht erreichbar.
  2. In ChatGPT Plugins das Plus wählen und Add custom MCP server öffnen.
  3. Einen Namen und eine Beschreibung vergeben und unter Connection die vollständige URL https://<Cloudron-App-Domain>/mcp eintragen.
  4. OAuth als Authentifizierung verwenden, den Risikohinweis prüfen und Create as a plugin wählen. ChatGPT entdeckt die OAuth-Endpunkte und registriert einen öffentlichen PKCE-Client dynamisch.
  5. Im geöffneten Sendewerk-Fenster mit dem eigenen Konto anmelden, Clientname und Rücksprung-Domain prüfen und den lesenden Zugriff ausdrücklich erlauben.
  6. Die gefundenen fünf Werkzeuge kontrollieren, das Plugin installieren und in einer neuen Unterhaltung über @ auswählen.

Eine erfolgreich lokale OAuth- und MCP-Prüfung beweist noch keine reale ChatGPT-Verbindung. Diese muss nach dem Cloudron-Update separat in der jeweiligen ChatGPT-Workspace-Konfiguration durchgeführt werden.

Befehle

Befehl Zweck
npm run setup Verzeichnisse, Migrationen und Seed für lokale Entwicklung
npm run db:migrate Ausstehende Migrationen atomar ausführen
npm run db:seed Reproduzierbare Beispieldaten laden
npm run dev Migrationen ausführen und Entwicklungsserver starten
npm run check Svelte- und TypeScript-Prüfung
npm run lint Formatierung und ESLint prüfen
npm test Verhaltenstests mit temporärer, getrennter Datenbank
npm run test:e2e Browserprüfungen gegen eine getrennte E2E-Datenbank
npm run build Produktionsartefakt in build/ erstellen
npm start gebautes Artefakt mit node build starten

Lokaler Produktionslauf

npm ci
npm run setup
export SENDEWERK_APP_ORIGIN=http://localhost:3000
npm run build
HOST=127.0.0.1 PORT=3000 npm start

Der Healthcheck liegt unter http://localhost:3000/healthz und prüft auch den Datenbankzugriff.

Für lokales HTTP wird das Sitzungscookie gezielt ohne Secure gesetzt, bleibt aber HttpOnly und SameSite=Lax. Bei einer https:-Origin ist Secure automatisch aktiv. Die Build-Origin muss beim lokalen Produktionsbuild mit der später verwendeten Browser-Origin übereinstimmen; SvelteKits Origin-Prüfung bleibt aktiv.

Vor der ersten Browserprüfung wird der Testbrowser einmalig installiert:

npx playwright install chromium
npm run test:e2e

Container und Cloudron

Das frühe Cloudron-Paket besteht aus Dockerfile, CloudronManifest.json und start.sh. Ein lokaler Container-Smoke-Test kann nach dem Build so erfolgen:

docker build -t sendewerk:local .
docker run --rm -p 3000:3000 \
  -e SENDEWERK_APP_ORIGIN=http://localhost:3000 \
  -e SENDEWERK_SETUP_TOKEN="$(openssl rand -hex 32)" \
  -v sendewerk-data:/app/data sendewerk:local

Auf Cloudron muss das Betreiber-Setup-Token vor dem ersten Browseraufruf als Umgebungsvariable gesetzt werden. CLOUDRON_APP_ORIGIN liefert dort die feste HTTPS-Origin. SMTP-Zugangsdaten werden ebenfalls ausschließlich als Laufzeitvariablen gesetzt, nicht in Manifest oder Image geschrieben.

Für MCP sind keine zusätzlichen Geheimnisse erforderlich. Seit Version 0.7.3 führt der bestehende Startprozess Migration 0020_oauth_mcp.sql aus. Anschließend muss die von Cloudron gelieferte HTTPS-Origin mit der in ChatGPT eingetragenen MCP-Domain übereinstimmen. Reverse Proxy und öffentliche Erreichbarkeit wurden ohne Cloudron-Zugang nicht geprüft.

Das ersetzt keinen Test auf einem echten Cloudron. Insbesondere Addon-Backup, Restore, Proxy-Origin und das read-only Laufzeitdateisystem können erst dort abschließend geprüft werden.

Dokumentation

  • docs/ARCHITECTURE.md: Systemgrenzen und geplanter Gesamtdatenbestand
  • docs/DECISIONS.md: technische Entscheidungen und offizielle Quellen
  • docs/ACCEPTANCE.md: Abnahmekriterien und konkrete Nachweise
  • docs/STATUS.md: aktueller Projektstand und bekannte Grenzen

Der Anwendungscode steht unter der MIT-Lizenz. Rechte an später eingestellten Medien und redaktionellen Inhalten werden dadurch nicht verändert.

Die direkten Laufzeit- und Werkzeugabhängigkeiten verwenden MIT- oder Apache-2.0-Lizenzen: Svelte/SvelteKit, Vite, Vitest, ESLint und better-sqlite3, @node-rs/argon2, Tiptap, Marked, sanitize-html, file-type und Metascraper sind MIT-lizenziert; Nodemailer verwendet MIT-0, TypeScript und Playwright stehen unter Apache-2.0. Die Lockdatei fixiert den tatsächlich installierten Baum.

S
Description
No description provided
Readme MIT
6.8 MiB
0 Stars 1 Watchers 0 Forks
2026-10-27 22:07:19 +00:00
Languages
TypeScript 67.1%
Svelte 16.5%
CSS 15.2%
JavaScript 1.1%