CommunityImagegithub.com

daily-card · Générateur de cartes sociales

Génère des cartes graphiques de style « citation du jour » ou « check-in » pour les réseaux sociaux (WeChat, Xiaohongshu, etc.). Utile lorsque l'utilisateur demande une carte avec titre, sous-titre, date et thème personnalisé.

Qu'est-ce que daily-card · Générateur de cartes sociales ?

Ce skill permet de générer des cartes sociales au format PNG à partir d'un titre et d'un sous-titre. La date du jour et des stickers vectoriels pertinents sont automatiquement ajoutés, avec une palette de couleurs cohérente. Le rendu est entièrement local, sans nécessité d'API ni de connexion Internet. Il est compatible avec les agents WorkBuddy, Claude Code et Codex CLI. L'agent exécute en priorité la commande CLI `python3 cardgen.py "titre" "sous-titre"`, puis présente le fichier PNG généré à l'utilisateur via `present_files`. Les paramètres permettent de choisir la plateforme (moments, xhs, wechat, story), le thème, la date, la marque en bas de carte, et même une image de fond avec extraction automatique des couleurs dominantes. Deux backends optionnels sont disponibles : un serveur web local avec aperçu en temps réel, et une API distante pour un usage partagé. La configuration des thèmes, couleurs et stickers se fait via des fichiers JSON privés, modifiables sans redémarrer le service. Le skill est conçu pour une intégration fluide dans les workflows d'agents : pas de service à lancer, pas de dépendance externe, résultats reproductibles.

Compatible avec✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/ChenKuan1110/daily-card/tree/HEAD

Installed? Explore more Image skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait daily-card · Générateur de cartes sociales ?

En une phrase

Entrez titre + sous-titre → obtenez un PNG : la date du jour, des stickers vectoriels en rapport avec le sujet et une palette de couleurs harmonieuse sont automatiquement ajoutés. Rendu local, texte chinois 100 % maîtrisé, résultats reproductibles avec les mêmes paramètres.

Ce dépôt est lui-même un répertoire de skill : le répertoire contenant ce SKILL.md est la racine du projet. Le code, les modèles de configuration et la documentation sont au même niveau. Il peut être placé dans les chemins de skills de WorkBuddy / Claude Code / Codex CLI, ou importé depuis GitHub par une plateforme de type skillhub.

Installation et emplacement

Racine du projet = répertoire contenant ce SKILL.md. Peut être placé n'importe où : le code utilise __file__ pour se localiser, pas de chemin absolu.

cd /path/to/daily-card          # Remplacez par l'emplacement réel
python3 -m pip install -r requirements.txt
./install.sh                    # Installation idempotente : dépendances, initialisation config privée, auto-vérification
./scripts/selfcheck.sh          # Auto-vérification ultérieure (également point d'entrée CI)

Pas besoin de réseau, pas d'interface IA, pas de clé API. Police chinoise détectée automatiquement : macOS utilise Hiragino Sans GB / PingFang, Linux utilise Noto Sans CJK, Windows utilise Microsoft YaHei ; si aucune n'est trouvée, le programme s'arrête en invitant à spécifier un fichier de police avec --font / --font-bold.

L'agent utilise en priorité la CLI locale, pas besoin de lancer de service. Le serveur web et l'API distante sont des backends optionnels, voir « Deux backends optionnels ».

Utilisation principale : génération en ligne de commande (priorité agent)

python3 cardgen.py "Profite bien de la vie" "Rends les jours ordinaires un peu plus brillants"

La commande affiche le chemin complet Fichier : ... ; présentez ce chemin PNG à l'utilisateur via present_files et expliquez le thème et les dimensions dans la réponse. Répertoire de sortie par défaut output/, nom du fichier <titre>-<date>-<plateforme>.png.

Paramètres courants

ParamètreRôleExemple
-t / -sTitre / Sous-titre-t "Bonjour" -s "Se lever d'abord"
--platformPréréglage de dimensionsxhs(1080×1440) / moments(1080×1080) / wechat(900×500) / story(1080×1920) / wechat2(1080×460)
--themeForcer un thème, par défaut détection automatique par mots-clés--theme study
--dateSpécifier une date--date 2026-01-01
--brandMarque en bas de carte--brand "Claw · Citation du jour"
--outSpécifier le chemin de sortie--out /tmp/carte.png
--seedGraine aléatoire de composition, même graine = même composition--seed 42
--bg-imageImage de fond personnalisée (extraction automatique des couleurs)--bg-image ./bg.jpg
--bg-schemeChoisir la N-ième palette de couleurs de l'image, ou une couleur personnalisée--bg-scheme 2 / --bg-scheme "#C2185B"
--list-schemesAfficher les palettes candidates de l'image de fond au format JSONpython3 cardgen.py --bg-image bg.jpg --list-schemes
--list-themesLister tous les thèmes et stickers
--config-dirUtiliser un autre répertoire de configuration
--init-configReconstruire config/themes.json à partir du modèle d'usine (écrase les thèmes privés, sauvegardez d'abord)

Processus complet d'extraction des couleurs d'une image de fond

# 1. Voir les palettes extractibles de l'image (retourne JSON : name / base / colors / ratio)
python3 cardgen.py --bg-image ./bg.jpg --list-schemes

# 2. Choisir une palette pour générer (0 est la couleur principale, 1/2/3 sont secondaires ; on peut aussi donner directement #RRGGBB)
python3 cardgen.py "Le crépuscule est la réponse du jour à la nuit" "Merci pour aujourd'hui" \
  --bg-image ./bg.jpg --bg-scheme 2 --platform xhs

Les couleurs (fond, texte, accent, carte, stickers) sont toutes dérivées de la palette choisie, donc les couleurs des stickers sont forcément dans la même gamme que l'image ; le type de sticker reste automatiquement attribué en fonction du thème du titre.

Fichiers de configuration (modifiez la configuration, pas le code)

FichierContenuVersionné ?
config/themes.default.jsonModèle d'usine, 11 thèmes, lecture seule, pour « rétablir les valeurs par défaut »Oui
config/stickers.json28 stickers (nom chinois / groupe) + registre de 6 motifs de fond (avec description sémantique desc)Oui
config/themes.jsonConfiguration réellement utilisée des thèmes : label, keywords, 10 couleurs, motif, stickers, darkNon, données privées
config/settings.jsonPlateforme par défaut, marque, facteur de suréchantillonnage, intensité du grain, répertoire de sortie, numéro de palette par défautNon, données privées

themes.json et settings.json sont des données privées de l'utilisateur, pas versionnées, pas publiées avec le dépôt public. Au premier lancement, cardconfig.ensure_config() les crée automatiquement à partir du modèle d'usine, pas besoin de création manuelle. Pour utiliser un autre répertoire de configuration, utilisez la variable d'environnement DAILY_CARD_CONFIG ou --config-dir. Voir config/README.md.

11 thèmes intégrés : study morning night coffee sport nature mood work tech festival quote.

Pour modifier les couleurs/stickers : éditez directement config/themes.json (couleurs / stickers / keywords du thème concerné), ou via l'API du backend. Le script relit la configuration à chaque exécution, les modifications sont prises en compte immédiatement. Pour ajouter un nouveau thème, incluez les 10 clés de couleur (#RRGGBB) et au moins un ID de sticker valide. Comme ce fichier est privé, les modifications n'apparaîtront pas dans git status. Sauvegardez-le manuellement si besoin.

Deux backends optionnels

BackendQuand ?Activation
Aucun (par défaut)Utilisez simplement la CLI pour générer des cartesNe rien faire, exécutez python3 cardgen.py ...
Serveur web local (mode autonome)Interface graphique, aperçu en temps réel, modification visuelle des thèmespython3 server.py (héberge page et API, interface sur http://127.0.0.1:8777)
Serveur distant (mode API uniquement)Partage en équipe, agent nécessite un endpoint stablepython3 server.py --api-only + proxy nginx (sous-chemin), définir DAILY_CARD_URL

En mode --api-only, le backend ne répond qu'aux /api/* (le statique est servi par nginx), /api/reveal retourne 403 ; GET /api/health affiche version / mode / serves_static / config_dir, utile pour vérifier la version en ligne.

La CLI s'exécute toujours sur la machine appelante, indépendamment du backend. Ne pas appeler /api/* si aucun service n'est démarré, cela échouera.

Serveur web local (configuration visuelle + aperçu en temps réel)

python3 server.py                 # http://127.0.0.1:8777 (mode autonome)
python3 server.py --port 9000 --open
python3 server.py --api-only       # Déploiement cloud : API uniquement, statique géré par nginx
# macOS : double-cliquez aussi sur start-server.command

Trois panneaux : Conception de carte (formulaire + aperçu en temps réel + téléchargement/sauvegarde), Configuration des thèmes (modification visuelle des couleurs/stickers/mots-clés et écriture dans le JSON), Paramètres globaux (valeurs par défaut et paramètres de rendu). Les onglets sont accessibles via #design / #config / #settings (liens profonds).

Le panneau de configuration des thèmes est en trois colonnes : liste des thèmes / éditeur / aperçu en temps réel. Lorsque vous modifiez une couleur, un motif de fond, l'option sombre ou les stickers, la colonne de droite affiche immédiatement un aperçu non sauvegardé de l'effet, incluant la vraie carte, le diagramme sémantique des couleurs (indiquant où chacune des 10 couleurs est utilisée, l'apparence réelle du motif actuel), l'apparence des stickers avec cette palette, et un diagnostic de contraste/conformité WCAG. L'aperçu est en mémoire en lecture seule, n'écrit pas dans config/themes.json. Cliquez sur « Sauvegarder la configuration » pour écrire sur le disque.

Déploiement sur un sous-chemin de domaine (serveur cloud)

Toutes les URL du frontend sont dérivées du BASE défini par web/app.js en runtime (document.baseURI), le code source n'a pas de racine de domaine en dur ; index.html utilise des chemins relatifs pour style.css / app.js. Pour pointer l'API vers un domaine différent, définissez window.DAILY_CARD_BASE avant de charger app.js. nginx se charge de retirer le préfixe /daily-card/api/* pour le transformer en /api/*, aucune modification du routage backend n'est nécessaire.

CommandeRôle
./scripts/publish-web.shPublier web/ dans un répertoire de version et basculer atomiquement le lien symbolique current
./scripts/publish-web.sh --listVoir les versions publiées et la version courante
./scripts/publish-web.sh --rollback [ver]Retour instantané, sans redémarrer Python
./scripts/test_subpath.pySimulation in-process du retrait de préfixe par nginx, 10 assertions de chaîne

Les versions statiques du frontend peuvent être publiées et annulées indépendamment du backend. Utilisez DAILY_CARD_WEB_ROOT (par défaut /opt/daily-card-web) et DAILY_CARD_WEB_KEEP (par défaut 5) pour les surcharger. La barre oblique finale est obligatoire : /daily-card doit rediriger (301) vers /daily-card/, sinon les chemins relatifs pointeront vers la racine du domaine. Voir docs/DEPLOY.md pour la configuration nginx complète, systemd, cache et authentification.

Lorsque l'agent appelle une interface distante, DAILY_CARD_URL doit être défini jusqu'au préfixe inclus, par exemple https://host/daily-card, le code construira https://host/daily-card/api/save ; ne pas mettre de nom de domaine nu.

Interface JSON (appelable directement par l'agent, sans navigateur)

InterfaceDescription
GET /api/healthVérification de santé : version, mode d'exécution, répertoire de configuration (pas besoin de lancer le frontend)
GET /api/bootstrapObtenir en une fois themes_doc / settings / registry / platforms / chemin
POST /api/renderGénérer un aperçu, retourne {png: dataURL, path, theme, size, bytes}
POST /api/saveGénérer et écrire dans output/, retourne le chemin
POST /api/theme-previewBrouillon de thème non sauvegardé → carte + diagramme sémantique + stickers + diagnostic de lisibilité, n'écrit pas le fichier de configuration
POST /api/schemesImage de fond → plusieurs palettes. Envoyer {"path":"/abs/bg.jpg"} ou {"image":"data:image/png;base64,..."}
GET /api/schemes?image_id=xxxRécupérer les palettes d'une image déjà téléchargée
POST /api/config/themes{"themes_doc": {...}} Sauvegarder la configuration des thèmes (avec validation)
POST /api/config/settings{"settings": {...}} Sauvegarder les paramètres globaux
POST /api/config/resetRestaurer les thèmes d'usine (écrase les thèmes privés, sauvegardez d'abord)
POST /api/revealOuvrir le dossier de sortie
GET /api/sticker?id=book&theme=studyIcône de sticker PNG

Corps de requête pour /api/render et /api/save :

{
  "title": "Profite bien de la vie",
  "subtitle": "Rends les jours ordinaires un peu plus brillants",
  "platform": "xhs",
  "theme": "auto",
  "date": null,
  "brand": "Claw · Citation du jour",
  "seed": null,
  "bg_image_id": null,
  "bg_path": "./bg.jpg",
  "bg_scheme": 0,
  "dark_override": null
}
  • bg_scheme peut être un index entier ou #RRGGBB ; dark_override = true/false force la carte claire/sombre, null suit l'image.
  • bg_image_id est retourné par /api/schemes ; on peut aussi donner directement bg_path accessible par le serveur.
  • Le png retourné est data:image/png;base64,..., à décoder pour écrire le fichier.

Exemple (quand DAILY_CARD_URL n'est pas défini, utilise localhost) :

DC_URL="${DAILY_CARD_URL:-http://127.0.0.1:8777}"
curl -s "$DC_URL/api/save" \
  -H 'Content-Type: application/json' \
  -d '{"title":"Profite bien de la vie","subtitle":"Rends les jours ordinaires un peu plus brillants","platform":"xhs"}' \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["path"])'

Aperçu du brouillon de thème / diagnostic de palette (inspectez avant de sauvegarder)

Pour juger si une palette est belle et le texte lisible avant de l'écrire dans la configuration, appelez /api/theme-preview. theme est un brouillon complet de thème, le serveur le garde uniquement en mémoire :

{
  "theme": {
    "label": "MON THÈME · Nouveau thème",
    "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": "Titre exemple",
  "subtitle": "Sous-titre exemple",
  "platform": "moments",
  "date": "2026-11-11",
  "seed": 7
}

Champs retournés (card / legend / stickers / sticker_sheet sont tous des data:image/png;base64,...) :

ChampSignification
cardCarte rendue avec ce brouillon
legendDiagramme sémantique des couleurs : motif réel + hiérarchie de la carte + rôle de chaque couleur
stickersApparence des stickers sélectionnés avec la palette courante
sticker_sheetSprite complet des stickers, avec sheet (cols/rows/cell/order) pour le découpage
diagnostics[{level: ok/warn/tip, text: explication en chinois}]
contrastValeurs de contraste (ink_card / sub_card / pill_pair / card_bg / accent_bg / bg_light)
motif / dark / draft_onlyNom du motif, indicateur clair/sombre, toujours true pour non sauvegardé

diagnostics vérifie le contraste selon WCAG : lisibilité du texte principal/secondaire/étiquette, distinction carte/fond, visibilité de la couleur d'accent, et contradictions comme « fond très sombre défini comme thème clair ». Méthode recommandée : envoyez d'abord le brouillon pour le diagnostic → s'il y a des warn, modifiez les couleurs selon les conseils et réessayez → une fois sans warn, appelez /api/config/themes pour sauvegarder.

Sans démarrer le backend, vous pouvez appeler directement le module :

import base64, cardconfig as cfg, cardpreview as cp
draft = cfg.load_doc()["themes"]["study"]        # Structure imbriquée, contient colors
draft["colors"]["accent"] = "#C2185B"            # Modifions pour voir
r = cp.build_preview({"theme": draft, "title": "Exemple", "subtitle": "Sous-titre"})
for it in r["diagnostics"]:
    print(it["level"], it["text"])
open("/tmp/draft-card.png", "wb").write(base64.b64decode(r["card"].split(",", 1)[1]))

Mise à jour et synchronisation multi-postes

La seule source de vérité pour les versions est le dépôt git, tous les autres postes sont des dérivés, flux unidirectionnel :

PosteMéthode de mise à jourConfiguration privée
Machine locale / serveur cloudgit pull && ./install.shNon affectée, non écrasée
Version statique frontend sur serveur cloud./scripts/publish-web.sh, --rollback pour retour instantanéDécouplé du service Python, pas de redémarrage
Enregistrement du skill sur la machine locale./install.sh --link-skill crée un lien symbolique (évite la dérive de copies)Non affectée
Snapshot sur plateforme skillhub, etc.Le mainteneur crée un tag puis réimporte, décalage de version naturelLa plateforme n'obtient que le modèle d'usine

Le modèle d'usine themes.default.json est mis à jour avec les versions. Le themes.json privé de l'utilisateur n'est jamais écrasé. Pour fusionner les nouveaux thèmes d'usine dans votre configuration, copiez manuellement les entrées depuis themes.default.json, ou utilisez dans le backend « Exporter JSON → Fusionner → Importer ». N'exécutez pas --init-config / /api/config/reset.

Voir docs/DEPLOY.md pour le déploiement serveur et l'intégration CI/CD. scripts/selfcheck.sh comporte 8 étapes, incluant la vérification de la portabilité des chemins frontend et la simulation de déploiement sur sous-chemin (proxy in-process, pas besoin d'installer nginx).

Workflow recommandé pour l'agent

  1. À partir des paroles de l'utilisateur, extraire le titre et le sous-titre (si pas de sous-titre, en ajouter un court et pertinent, ou laisser vide).
  2. Déterminer la plateforme : si non précisée, utiliser xhs ; si mentionné « article WeChat » utiliser wechat, « Moments » utiliser moments.
  3. Si l'utilisateur fournit une image de fond : d'abord --list-schemes ou /api/schemes pour voir les candidates, puis utiliser la sélectionnée ; si non précisé, utiliser le schéma 0.
  4. Exécuter la CLI (pas besoin de service) ; n'appeler /api/save que si l'utilisateur demande explicitement un backend/accès distant.
  5. Présenter l'image finale avec present_files, en indiquant dans la réponse le thème, les dimensions, la date et la palette de couleurs.
  6. Si l'utilisateur veut changer le style → modifier config/themes.json ou le panneau de configuration du backend, ne pas modifier cardgen.py.

Remarques importantes

  • Répartition du code : cardgen.py ne s'occupe que du rendu, cardconfig.py du chargement/sauvegarde de la configuration et de l'extraction des couleurs, cardpreview.py de l'aperçu du brouillon et du diagnostic de palette, server.py est le backend. Tous lisent les mêmes config/*.json.
  • output/, uploads/, config/themes.json, config/settings.json, .env sont ignorés par .gitignore ; examples/ contient des démos (environ 6.7 Mo, non nécessaires au fonctionnement, peuvent être supprimés à tout moment).
  • Les ID de thème acceptent uniquement les lettres, chiffres, -, _ ; les couleurs doivent être en #RRGGBB ; les ID de stickers doivent exister dans config/stickers.json.
  • Plus l'image est grande et le suréchantillonnage élevé, plus c'est lent ; le suréchantillonnage 2x par défaut est suffisamment net.
  • server.py n'a aucune authentification et écoute par défaut seulement 127.0.0.1. Avant un déploiement public, ajoutez une authentification par proxy inverse ou une liste blanche IP ; pour le cloud, utilisez --api-only pour exposer uniquement l'API, voir docs/DEPLOY.md.
  • Le code source ne doit pas contenir de chemins absolus comme src="/..." / href="/..." / "/api/..." ; selfcheck.sh bloque ces régressions ; toutes les requêtes passent par url().

Limitations connues / Plan pour la prochaine version

  • Pas de téléchargement personnalisé de stickers (version actuelle) : les stickers sont limités aux 28 stickers vectoriels enregistrés dans config/stickers.json. Il n'y a pas de module de gestion de bibliothèque de stickers indépendant, et le téléchargement de PNG/SVG comme sticker n'est pas supporté. Pour ajouter une forme, le développeur doit actuellement ajouter une fonction de dessin s_xxx dans cardgen.py et l'enregistrer dans stickers.json.
  • Plan pour la prochaine version : téléchargement personnalisé de stickers (PNG/SVG, avec adaptation automatique des couleurs au thème), panneau de gestion de bibliothèque de stickers (ajout/suppression/modification / regroupement / aperçu / réutilisation), découplage stickers/thèmes. L'utilisateur a clairement indiqué que cette fonctionnalité est repoussée à la prochaine version, non implémentée ici.
  • L'aperçu du brouillon de thème utilise un suréchantillonnage 1x pour accélérer la réponse, légèrement différent du rendu final 2x pour les détails les plus fins, mais la mise en page et les couleurs sont les mêmes.

Skills associés