daily-card · Generator für soziale Karten
Auf einen Satz
Titel + Untertitel eingeben → PNG ausgeben: automatisch mit aktuellem Datum, thematisch passenden Vektor-Stickern und einheitlichem Farbschema. Reine lokale Darstellung, chinesische Schrift 100% kontrollierbar, Ergebnisse bei gleichen Parametern reproduzierbar.
Dieses Repository ist selbst ein Skill-Verzeichnis: Das Verzeichnis, in dem sich diese SKILL.md befindet, ist das Projektstammverzeichnis. Code, Konfigurationsvorlagen und Dokumentation sind auf derselben Ebene. Kann in die jeweiligen Skills-Pfade von WorkBuddy / Claude Code / Codex CLI usw. gelegt oder von einer Skillhub-Plattform von GitHub importiert werden.
Installation und Standort
Projektstamm = Verzeichnis dieser SKILL.md. Kann von jedem Pfad aus ausgeführt werden – der Code verwendet __file__ zur Standortbestimmung und ist nicht von absoluten Pfaden abhängig.
cd /path/to/daily-card # Durch tatsächlichen Installationspfad ersetzen
python3 -m pip install -r requirements.txt
./install.sh # Idempotente Installation: Abhängigkeiten, private Konfigurationsinitialisierung, Selbsttest
./scripts/selfcheck.sh # Danach jederzeit einzeln ausführbar (auch CI-Einstiegspunkt)
Keine Internetverbindung, keine KI-Schnittstelle, kein API-Schlüssel erforderlich. Chinesische Schriftarten werden automatisch erkannt: macOS verwendet Hiragino Sans GB / PingFang, Linux Noto Sans CJK, Windows Microsoft YaHei; falls keine gefunden wird, wird abgebrochen und auf die Angabe einer Schriftartendatei mit --font / --font-bold hingewiesen.
Agenten verwenden bevorzugt die lokale CLI, kein Starten eines Dienstes erforderlich. Das Web-Backend und die Remote-API sind optionale Optionen, siehe „Zwei optionale Backends".
Am häufigsten verwendet: Kommandozeilengenerierung (bevorzugt für Agenten)
python3 cardgen.py "Heute auch gut leben" "Den gewöhnlichen Tag etwas lauter machen"
Der Befehl gibt den vollständigen Pfad unter Datei: ... aus; dieses PNG-Pfad dem Benutzer mittels present_files übergeben und in der Antwort das Thema und die Größe erläutern. Standardausgabeverzeichnis output/, Dateiname <Titel>-<Datum>-<Plattform>.png.
Häufig verwendete Parameter
| Parameter | Wirkung | Beispiel |
|---|---|---|
-t / -s | Titel / Untertitel | -t "Guten Morgen" -s "Erst aufstehen" |
--platform | Größenpreset | xhs(1080×1440) / moments(1080×1080) / wechat(900×500) / story(1080×1920) / wechat2(1080×460) |
--theme | Thema erzwingen, Standard automatisch nach Schlüsselwort | --theme study |
--date | Datum angeben | --date 2026-01-01 |
--brand | Fußzeile | --brand "Claw · Tägliches Zitat" |
--out | Ausgabepfad angeben | --out /tmp/card.png |
--seed | Zufallsgenerator-Seed für Layout, gleicher Seed gleiches Layout | --seed 42 |
--bg-image | Benutzerdefiniertes Hintergrundbild (automatische Farberkennung) | --bg-image ./bg.jpg |
--bg-scheme | N-tes Farbschema des Bildes oder benutzerdefinierte Hauptfarbe auswählen | --bg-scheme 2 / --bg-scheme "#C2185B" |
--list-schemes | Kandidaten-Farbschemata des Hintergrundbildes als JSON ausgeben | python3 cardgen.py --bg-image bg.jpg --list-schemes |
--list-themes | Alle Themen und Sticker auflisten | |
--config-dir | Ein anderes Konfigurationsverzeichnis verwenden | |
--init-config | config/themes.json aus der Werkseinstellungsvorlage neu erstellen (überschreibt private Themen, vorher sichern) |
Vollständiger Ablauf der Farberkennung aus Hintergrundbildern
# 1. Zuerst sehen, welche Farbschemata aus dem Bild extrahiert werden können (gibt JSON zurück: name / base / colors / ratio)
python3 cardgen.py --bg-image ./bg.jpg --list-schemes
# 2. Eines auswählen und generieren (0 ist Hauptfarbe, 1/2/3 sind Nebenfarben; oder direkt #RRGGBB angeben)
python3 cardgen.py "Die Abenddämmerung ist die Antwort des Tages an die Nacht" "Heute auch hart gearbeitet" \
--bg-image ./bg.jpg --bg-scheme 2 --platform xhs
Farben (Hintergrund, Text, Akzent, Karte, Sticker) werden alle aus dem ausgewählten Schema abgeleitet, sodass die Stickerfarben zwangsläufig mit dem Bild harmonieren; die Stickerart wird weiterhin automatisch nach dem Titelthema zugeordnet.
Konfigurationsdateien (Konfiguration ändern, nicht den Code)
| Datei | Inhalt | Im Repository? |
|---|---|---|
config/themes.default.json | Werkseinstellungsvorlage, 11 Themen, schreibgeschützt, für „Wiederherstellung der Standardeinstellungen" | Ja |
config/stickers.json | 28 Sticker (chinesische Namen/Gruppen) + 6 Hintergrundmuster-Registry (mit semantischer Beschreibung desc) | Ja |
config/themes.json | Tatsächlich verwendete Themenkonfiguration: Label, Keywords, 10 Farben, motif, stickers, dark | Nein, private Daten |
config/settings.json | Standardplattform, Fußzeile, Oversampling-Faktor, Kornstärke, Ausgabeverzeichnis, Standard-Farbschema-Nummer | Nein, private Daten |
themes.json und settings.json sind private Daten des Benutzers, nicht versioniert und nicht mit dem öffentlichen Repository veröffentlicht. Beim ersten Start erstellt cardconfig.ensure_config() automatisch eine Kopie aus der Werkseinstellungsvorlage, manuelle Erstellung nicht erforderlich. Für ein anderes Konfigurationsverzeichnis die Umgebungsvariable DAILY_CARD_CONFIG oder --config-dir verwenden. Siehe config/README.md.
11 integrierte Themen: study morning night coffee sport nature mood work tech festival quote.
Farben/Sticker ändern: Direkt config/themes.json bearbeiten (entsprechendes Thema colors / stickers / keywords) oder über das Backend-API; das Skript liest bei jedem Lauf neu, Änderungen sofort wirksam. Neue Themen müssen alle 10 Farbschlüssel (#RRGGBB) und mindestens eine gültige Sticker-ID enthalten. Da es sich um private Daten handelt, erscheinen Änderungen nicht in git status; zur Sicherung bitte die Datei kopieren.
Zwei optionale Backends
| Backend | Wann benötigt? | Aktivierung |
|---|---|---|
| Keines (Standard) | Nur CLI zum Kartengenerieren | Nichts tun, direkt python3 cardgen.py ... |
| Lokales Web-Backend (eigenständiger Modus) | GUI, Echtzeitvorschau, visuelle Themenbearbeitung | python3 server.py, hostet sowohl Seite als auch API, Schnittstelle unter http://127.0.0.1:8777 |
| Remote-Server (reiner API-Modus) | Teamfreigabe, Agent benötigt stabilen Endpunkt | python3 server.py --api-only + nginx Sub-Pfad Reverse Proxy, DAILY_CARD_URL setzen |
Im --api-only-Modus antwortet das Backend nur auf /api/* (statische Dateien von nginx direkt ausgeliefert), /api/reveal gibt 403 zurück; GET /api/health gibt version / mode / serves_static / config_dir aus, nützlich zum Abgleich der online-Version.
Die CLI wird immer lokal auf dem aufrufenden Rechner ausgeführt, unabhängig vom Backend. Wenn kein Dienst läuft, nicht /api/* aufrufen, sonst Verbindungsfehler.
Lokales Web-Backend (visuelle Konfiguration + Echtzeitvorschau)
python3 server.py # http://127.0.0.1:8777 (eigenständiger Modus)
python3 server.py --port 9000 --open
python3 server.py --api-only # Cloud-Bereitstellung: nur API, statische Dateien von nginx
# macOS: Doppelklick start-server.command
Drei Panels: Kartendesign (Formular + Echtzeitvorschau + Download/Speichern), Themenkonfiguration (visuelle Farb-/Sticker-/Schlüsselwortbearbeitung und Zurückschreiben in JSON), Globaleinstellungen (Standardwerte und Rendering-Parameter). Tabs über #design / #config / #settings Deep-Linking erreichbar.
Das Themenkonfigurationspanel ist dreispaltig: Themenliste / Editor / Echtzeiteffektvorschau. Beim Bearbeiten von Farben, Hintergrundmustern, Dark-Mode-Schalter, Stickern wird auf der rechten Seite sofort der ungespeicherte Entwurfseffekt angezeigt, einschließlich echter Karte, Farbsemantik-Diagramm (markiert, wo die 10 Farben jeweils verwendet werden, wie das aktuelle Muster tatsächlich aussieht), Sticker in dieser Farbgebung sowie WCAG-Kontrast-/Helligkeitskonsistenz-Diagnose. Die Vorschau befindet sich nur im RAM, schreibt nicht in config/themes.json; erst bei Zufriedenheit auf „Konfiguration speichern" klicken, um sie zu speichern.
Bereitstellung unter Sub-Pfad auf gleicher Domain (Cloud-Server)
Frontend-URLs werden alle von der Laufzeit-BASE in web/app.js abgeleitet (document.baseURI), der Quellcode hardcodiert keine Domain-Wurzelpfade; index.html verwendet für style.css / app.js ebenfalls relative Pfade. Wenn die API auf eine separate Domain zeigen soll, vor dem Laden von app.js window.DAILY_CARD_BASE setzen. nginx entfernt das Präfix /daily-card/api/* zu /api/*, Backend-Routing muss nicht geändert werden.
| Befehl | Wirkung |
|---|---|
./scripts/publish-web.sh | web/ in ein Versionsverzeichnis veröffentlichen und current Symlink atomar wechseln |
./scripts/publish-web.sh --list | Veröffentlichte Versionen und aktuellen Symlink anzeigen |
./scripts/publish-web.sh --rollback [ver] | Sekundenschnelles Rollback, kein Neustart von Python erforderlich |
./scripts/test_subpath.py | Prozessinterne Simulation des nginx-Präfix-Entfernens, 10 Kettentests |
Frontend-Statikversionen können unabhängig vom Backend veröffentlicht und zurückgesetzt werden. Überschreibbar mit DAILY_CARD_WEB_ROOT (Standard /opt/daily-card-web) und DAILY_CARD_WEB_KEEP (Standard 5). Schrägstrich am Ende ist zwingend erforderlich: /daily-card muss per 301 auf /daily-card/ umleiten, sonst werden relative Pfade auf die Domain-Wurzel aufgelöst. Vollständige nginx-Konfiguration, systemd, Cache und Authentifizierung siehe docs/DEPLOY.md.
Wenn der Agent die Remote-Schnittstelle aufruft, muss DAILY_CARD_URL bis zum Präfix angegeben werden, z.B. https://host/daily-card; der Code setzt daraus https://host/daily-card/api/save; nicht den nackten Domainnamen angeben.
JSON-Schnittstelle (Agent kann direkt aufrufen, kein Browser erforderlich)
| Schnittstelle | Beschreibung |
|---|---|
GET /api/health | Health-Check: Version, Betriebsmodus, Konfigurationsverzeichnis (kein Start des Frontends erforderlich) |
GET /api/bootstrap | Holt auf einmal themes_doc / settings / registry / platforms / paths |
POST /api/render | Vorschau generieren, gibt {png: dataURL, path, theme, size, bytes} zurück |
POST /api/save | Generieren und in output/ speichern, gibt den gespeicherten Pfad zurück |
POST /api/theme-preview | Nicht gespeicherter Themenentwurf → Karte + Semantikdiagramm + Stickerstreifen + Lesbarkeitsdiagnose, schreibt keine Konfigurationsdatei |
POST /api/schemes | Hintergrundbild → mehrere Farbschemata. Übergabe {"path":"/abs/bg.jpg"} oder {"image":"data:image/png;base64,..."} |
GET /api/schemes?image_id=xxx | Schema des bereits hochgeladenen Bildes erneut abrufen |
POST /api/config/themes | {"themes_doc": {...}} Themenkonfiguration speichern (mit Validierung) |
POST /api/config/settings | {"settings": {...}} Globaleinstellungen speichern |
POST /api/config/reset | Themen auf Werkseinstellungen zurücksetzen (überschreibt private Themen, vorher sichern) |
POST /api/reveal | Ausgabeverzeichnis öffnen |
GET /api/sticker?id=book&theme=study | Sticker-Icon als PNG |
Anforderungskörper für /api/render und /api/save:
{
"title": "Heute auch gut leben",
"subtitle": "Den gewöhnlichen Tag etwas lauter machen",
"platform": "xhs",
"theme": "auto",
"date": null,
"brand": "Claw · Tägliches Zitat",
"seed": null,
"bg_image_id": null,
"bg_path": "./bg.jpg",
"bg_scheme": 0,
"dark_override": null
}
bg_schemekann eine ganze Zahl (Index) oder#RRGGBBsein;dark_overridealstrue/falseerzwingt helle/dunkle Karte,nullfolgt der Bildbewertung.bg_image_idwird von/api/schemeszurückgegeben; alternativ kann direktbg_pathmit einem serverseitig erreichbaren Pfad angegeben werden.- Das zurückgegebene
pngistdata:image/png;base64,..., dekodieren und als Datei speichern.
Beispiel (wenn DAILY_CARD_URL nicht gesetzt, wird lokal verwendet):
DC_URL="${DAILY_CARD_URL:-http://127.0.0.1:8777}"
curl -s "$DC_URL/api/save" \
-H 'Content-Type: application/json' \
-d '{"title":"Heute auch gut leben","subtitle":"Den Tag etwas lauter machen","platform":"xhs"}' \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["path"])'
Themenentwurfsvorschau / Farbdiagnose (Qualitätskontrolle vor dem Speichern)
Um vor dem Schreiben der Konfiguration zu beurteilen, ob ein Farbschema gut aussieht und der Text lesbar ist, /api/theme-preview aufrufen. theme ist der vollständige Themenentwurf, der nur im RAM des Servers bleibt:
{
"theme": {
"label": "MEIN THEMA · Neues Thema",
"keywords": ["Check-in"],
"motif": "dots",
"dark": false,
"colors": {
"bg1": "#F7E9C8", "bg2": "#EED6A4", "card": "#FFFCF6",
"ink": "#2E3A2C", "sub": "#6D7570", "accent": "#E0703C",
"accent2": "#5D8B6A", "soft": "#F1D9A8", "pill": "#2E3A2C",
"pill_text": "#FFFDF5"
},
"stickers": ["book", "pencil", "sun"]
},
"title": "Beispieltitel",
"subtitle": "Beispieluntertitel",
"platform": "moments",
"date": "2026-11-11",
"seed": 7
}
Rückgabefelder (card / legend / stickers / sticker_sheet sind alle data:image/png;base64,...):
| Feld | Bedeutung |
|---|---|
card | Mit diesem Entwurf tatsächlich gerenderte Karte |
legend | Semantische Farbschemadarstellung: Echtes Muster + Kartenebenen + wofür die 10 Farben jeweils zuständig |
stickers | Ausgewählte Sticker in der aktuellen Farbgebung |
sticker_sheet | Vollständiges Sticker-Sprite, zusammen mit sheet (cols/rows/cell/order) zum Ausschneiden und Anzeigen |
diagnostics | [{level: ok/warn/tip, text: chinesische Erklärung}] |
contrast | Verschiedene Kontrastwerte (ink_card / sub_card / pill_pair / card_bg / accent_bg / bg_light) |
motif / dark / draft_only | Muster-Name und Beschreibung, Helligkeitsmarkierung, immer true für „noch nicht gespeichert" |
diagnostics prüft gemäß WCAG-Kontrast: Lesbarkeit von Haupttext/Nebentext/Labeltext, Abgrenzung Karte zu Hintergrund, ob die Akzentfarbe ausreichend hervorsticht, sowie Widersprüche wie „sehr dunkler Hintergrund, aber helles Thema". Empfohlenes Vorgehen: Zuerst POST-Entwurf und Diagnose ansehen → bei warn die Farbe entsprechend dem Hinweis ändern und erneut ausführen → erst ohne warn dann /api/config/themes zum Speichern aufrufen.
Auch ohne laufendes Backend kann das Modul direkt aufgerufen werden:
import base64, cardconfig as cfg, cardpreview as cp
draft = cfg.load_doc()["themes"]["study"] # Verschachtelte Struktur, enthält colors
draft["colors"]["accent"] = "#C2185B" # Einmal testweise ändern
r = cp.build_preview({"theme": draft, "title": "Beispiel", "subtitle": "Untertitel"})
for it in r["diagnostics"]:
print(it["level"], it["text"])
open("/tmp/draft-card.png", "wb").write(base64.b64decode(r["card"].split(",", 1)[1]))
Aktualisierung und Multi-Endpunkt-Synchronisation
Einzige Wahrheitsquelle ist das Git-Repository; alle anderen Endpunkte sind Ableitungen und nur unidirektional:
| Endpunkt | Aktualisierungsmethode | Private Konfiguration |
|---|---|---|
| Lokal / Cloud-Server | git pull && ./install.sh | Nicht betroffen, wird nicht überschrieben |
| Frontend-Statikversion auf Cloud-Server | ./scripts/publish-web.sh, --rollback für sofortiges Rollback | Entkoppelt vom Python-Dienst, kein Neustart erforderlich |
| Lokale Skill-Registrierung | ./install.sh --link-skill erstellt symbolischen Link, vermeidet Dateikopie-Drift | Nicht betroffen |
| Snapshot auf Skillhub etc. | Verantwortlicher erstellt Tag und importiert neu, natürliche Versionsverzögerung | Plattform erhält nur die Werkseinstellungsvorlage |
Die Werkseinstellungsvorlage themes.default.json wird mit den Versionen aktualisiert; das private themes.json des Benutzers wird niemals überschrieben. Um die neuen Werkseinstellungsthemen in die eigene Konfiguration zu integrieren, manuell die entsprechenden Einträge aus themes.default.json kopieren oder im Backend „Export JSON → Zusammenführen → Importieren" verwenden, nicht direkt --init-config / /api/config/reset ausführen.
Server-Bereitstellung und CI/CD-Integration siehe docs/DEPLOY.md. scripts/selfcheck.sh besteht aus 8 Schritten, einschließlich Frontend-Pfad-Portabilitätsprüfung und Sub-Pfad-Bereitstellungssimulation (in-process Proxy, kein echter nginx erforderlich).
Empfohlener Workflow für Agenten
- Aus Benutzeraussagen Titel und Untertitel extrahieren (wenn kein Untertitel gegeben, einen passenden kurzen Satz ergänzen oder leer lassen).
- Plattform erkennen: wenn nicht genannt,
xhsverwenden; für offizielle Kontenwechat, für Momentemoments. - Wenn der Benutzer ein Hintergrundbild angibt: zuerst
--list-schemesoder/api/schemesfür Kandidaten aufrufen, dann mit Auswahl generieren; falls nicht angegeben, Schema 0 verwenden. - CLI ausführen (kein Dienst erforderlich); nur wenn der Benutzer explizit das Backend/Remote nutzen möchte,
/api/saveaufrufen. - Das fertige Bild mit present_files anzeigen, in der Antwort Thema, Größe, Datum und Farbschema erläutern.
- Benutzer möchte Stil ändern →
config/themes.jsonbearbeiten oder das Backend-Konfigurationspanel verwenden, nichtcardgen.pyändern.
Hinweise
- Code-Aufteilung:
cardgen.pyist nur fürs Rendern zuständig,cardconfig.pyfür Konfigurationsladen/Speichern/Farberkennung,cardpreview.pyfür Themenentwurfsvorschau und Farbdiagnose,server.pyist das Backend; alle lesen dieselbenconfig/*.json. output/,uploads/,config/themes.json,config/settings.json,.envwerden alle von.gitignoreignoriert;examples/enthält Demo-Endproduktbilder (ca. 6,7 MB, nicht am Betrieb beteiligt, können jederzeit gelöscht werden).- Themen-IDs erlauben nur alphanumerische Zeichen,
-,_; Farben müssen#RRGGBBsein; Sticker-IDs müssen inconfig/stickers.jsonvorhanden sein. - Je größer das Bild und je höher das Oversampling, desto langsamer; Standard 2x Oversampling ist bereits ausreichend scharf.
server.pyhat keine Authentifizierung und hört standardmäßig nur auf127.0.0.1. Vor öffentlicher Bereitstellung unbedingt Reverse-Proxy-Authentifizierung oder IP-Whitelist hinzufügen; für Cloud-Bereitstellung--api-onlyverwenden, um nur die API freizugeben, Details indocs/DEPLOY.md.- Im Quellcode sind keine absoluten Pfade wie
src="/..."/href="/..."/"/api/..."erlaubt;selfcheck.shblockiert solche Regressionen; alle Anfragen werden einheitlich überurl()abgewickelt.
Bekannte Einschränkungen / Nächste Version
- Benutzerdefinierte Sticker können nicht hochgeladen werden (aktuelle Version): Sticker können nur aus den 28 registrierten Vektor-Stickern in
config/stickers.jsonausgewählt werden. Es gibt kein separates Sticker-Bibliotheksverwaltungsmodul, und das Hochladen von PNG/SVG als Sticker wird nicht unterstützt. Um eine Form hinzuzufügen, muss der Entwickler derzeit eines_xxx-Zeichenfunktion incardgen.pyhinzufügen und instickers.jsonregistrieren. - Nächste Version geplant: Benutzerdefinierte Sticker-Uploads (PNG/SVG, automatische Farberkennung zur Anpassung an das Thema), Sticker-Bibliotheksverwaltungspanel (Hinzufügen/Löschen / Gruppieren / Vorschau / Wiederverwenden), Entkopplung von Stickern und Themen. Der Benutzer hat bereits bestätigt, dass dies in der nächsten Version umgesetzt wird und in dieser Version nicht enthalten ist.
- Die Themenentwurfsvorschau verwendet 1x Oversampling für schnellere Reaktionszeiten und weicht im Feinstkorn geringfügig von der finalen 2x-Ausgabe ab, Layout und Farbgebung sind jedoch identisch.