daily-card · 社交卡片產生器
能力一句話
輸入 標題 + 副標題 → 輸出一張 PNG:自動包含當天日期、與文案主題相關的向量貼紙、成套統一的配色。純本地渲染,中文文字 100% 可控,同參數結果可複現。
這個倉庫本身就是一個 skill 目錄:本 SKILL.md 所在目錄即專案根,程式碼、設定範本、文件都在同級。可放進 WorkBuddy / Claude Code / Codex CLI 等各自的 skills 路徑,也可由 skillhub 類平台從 GitHub 匯入。
安裝與位置
專案根 = 本 SKILL.md 所在目錄。放到任何路徑都能跑——程式碼用 __file__ 定位,不依賴絕對路徑。
cd /path/to/daily-card # 換成實際安裝位置
python3 -m pip install -r requirements.txt
./install.sh # 幂等安裝:依賴、私有設定初始化、自檢
./scripts/selfcheck.sh # 之後隨時可單獨自檢(也是 CI 入口)
不需要連網、不需要 AI 介面、不需要 API Key。中文字體自動偵測:macOS 用 Hiragino Sans GB / PingFang,Linux 用 Noto Sans CJK,Windows 用微軟雅黑;都找不到時會退出並提示用 --font / --font-bold 指定字體檔案。
agent 優先使用本地 CLI,不需要啟動任何服務。 網頁後台與遠端 API 都是可選後端,見「兩種可選後端」。
最常用:命令列生成(agent 優先使用這條)
python3 cardgen.py "今天也要好好生活" "把普通的日子,過得響亮一點"
指令會印出 檔案: 的完整路徑;把這個 PNG 路徑用 present_files 交給使用者,並在回覆裡說明主題和尺寸。預設輸出目錄 output/,檔名 <標題>-<日期>-<平台>.png。
常用參數
| 參數 | 作用 | 範例 |
|---|---|---|
-t / -s | 標題 / 副標題 | -t "早安" -s "先起床" |
--platform | 尺寸預設 | xhs(1080×1440) / moments(1080×1080) / wechat(900×500) / story(1080×1920) / wechat2(1080×460) |
--theme | 強制主題,預設按關鍵字自動識別 | --theme study |
--date | 指定日期 | --date 2026-01-01 |
--brand | 底部落款 | --brand "Claw · 每日一句" |
--out | 指定輸出路徑 | --out /tmp/card.png |
--seed | 構圖隨機種子,同樣種子同樣構圖 | --seed 42 |
--bg-image | 自訂背景圖(自動取色) | --bg-image ./bg.jpg |
--bg-scheme | 選用第 N 套圖片配色,或自訂主色 | --bg-scheme 2 / --bg-scheme "#C2185B" |
--list-schemes | 輸出背景圖的候選配色方案 JSON | python3 cardgen.py --bg-image bg.jpg --list-schemes |
--list-themes | 列出全部主題與貼紙 | |
--config-dir | 使用另一套設定目錄 | |
--init-config | 從出廠範本重建 config/themes.json(會覆蓋私有主題,先備份) |
背景圖取色的完整流程
# 1. 先看圖片能提取出哪幾套配色(返回 JSON:name / base / colors / ratio)
python3 cardgen.py --bg-image ./bg.jpg --list-schemes
# 2. 選一套生成(0 是主色,1/2/3 是輔色;也可以直接給 #RRGGBB)
python3 cardgen.py "黃昏是白天給夜晚的回信" "今天也辛苦了" \
--bg-image ./bg.jpg --bg-scheme 2 --platform xhs
配色(背景、文字、強調色、卡片、貼紙)全部由選中的方案派生,所以貼紙顏色必定與畫面同色系;貼紙種類仍按標題主題自動匹配。
設定檔案(改設定,不要改程式碼)
| 檔案 | 內容 | 是否進倉庫 |
|---|---|---|
config/themes.default.json | 出廠範本,11 套主題,唯讀,用於「恢復預設」 | 是 |
config/stickers.json | 28 個貼紙的中文名/分組 + 6 種背景紋樣註冊表(含語義說明 desc) | 是 |
config/themes.json | 實際生效的主題設定:label、keywords、10 個顏色、motif、stickers、dark | 否,私有資料 |
config/settings.json | 預設平台、落款、超取樣倍數、顆粒強度、輸出目錄、預設配色方案序號 | 否,私有資料 |
themes.json 與 settings.json 屬於使用者私有資料,不進版本管理、不隨公開倉庫發布。首次執行時 cardconfig.ensure_config() 會自動從出廠範本複製生成,無需手動建立。想換一套設定目錄用 DAILY_CARD_CONFIG 環境變數或 --config-dir。詳見 config/README.md。
內建 11 套主題:study morning night coffee sport nature mood work tech festival quote。
要改配色/貼紙時:直接編輯 config/themes.json 對應主題的 colors / stickers / keywords,或走後台 API;腳本每次執行都重新讀取,改完立即生效。新增主題需包含全部 10 個顏色鍵(#RRGGBB)、至少一個合法貼紙 ID。因為它是私有資料,改完不會出現在 git status 裡,需要備份請自行複製該檔案。
兩種可選後端
| 後端 | 何時需要 | 啟用方式 |
|---|---|---|
| 無(預設) | 只要用 CLI 生成卡片 | 什麼都不做,直接 python3 cardgen.py ... |
| 本地網頁後台(獨立模式) | 要 GUI、即時預覽、可視化改主題 | python3 server.py,同時託管頁面與 API,介面在 http://127.0.0.1:8777 |
| 遠端伺服器(純 API 模式) | 團隊共享、agent 需要穩定端點 | python3 server.py --api-only + nginx 子路徑反代,設 DAILY_CARD_URL |
--api-only 下後端只回答 /api/*(靜態由 nginx 直出),/api/reveal 返回 403;GET /api/health 回顯 version / mode / serves_static / config_dir,可用於核對線上版本。
CLI 始終在呼叫方本機執行,與後端無關。沒有啟動服務時不要調 /api/*,會連線失敗。
本地網頁後台(可視化設定 + 即時預覽)
python3 server.py # http://127.0.0.1:8777(獨立模式)
python3 server.py --port 9000 --open
python3 server.py --api-only # 雲端部署:只提供 API,靜態由 nginx 託管
# macOS 也可雙擊 start-server.command
三個面板:卡片設計(表單 + 即時預覽 + 下載/儲存)、主題設定(可視化改顏色/貼紙/關鍵字並寫回 JSON)、全域設定(預設值與渲染參數)。Tab 可用 #design / #config / #settings 深鏈。
主題設定面板是三欄:主題列表 / 編輯器 / 即時效果預覽。編輯顏色、背景紋樣、深色開關、貼紙時,右側會立刻顯示尚未儲存的草稿效果,包括真實卡片、配色語義圖(標註 10 個顏色各用在哪、當前紋樣實際長什麼樣)、貼紙在該配色下的樣子,以及 WCAG 對比度/明暗一致性診斷。預覽只讀記憶體,不會寫 config/themes.json,滿意後點「儲存設定」才落盤。
同域名子路徑部署(雲端伺服器)
前端 URL 全部由 web/app.js 頂部的執行時 BASE 派生(document.baseURI),原始碼不寫死域名根路徑;index.html 的 style.css / app.js 也用相對路徑。需要把 API 指向獨立域名時,在載入 app.js 前設定 window.DAILY_CARD_BASE。nginx 負責把 /daily-card/api/* 剝前綴成 /api/*,後端路由無需改動。
| 指令 | 作用 |
|---|---|
./scripts/publish-web.sh | 發布 web/ 到版本目錄並原子切換 current 軟鏈 |
./scripts/publish-web.sh --list | 查看已發布版本與當前指向 |
./scripts/publish-web.sh --rollback [ver] | 秒回滾,不需要重啟 Python |
./scripts/test_subpath.py | 進程內模擬 nginx 剝前綴,10 項鏈路斷言 |
前端靜態版本可獨立於後端發版與回滾。可用 DAILY_CARD_WEB_ROOT(預設 /opt/daily-card-web)與 DAILY_CARD_WEB_KEEP(預設 5)覆蓋。尾斜線是硬要求:/daily-card 必須 301 到 /daily-card/,否則相對路徑會解析回域名根。完整 nginx 設定、systemd、快取與鑑權見 docs/DEPLOY.md。
agent 調遠端介面時,DAILY_CARD_URL 要填到前綴為止,例如 https://host/daily-card,程式碼會拼成 https://host/daily-card/api/save;不要填成裸域名。
JSON 介面(agent 可直接呼叫,無需瀏覽器)
| 介面 | 說明 |
|---|---|
GET /api/health | 健康檢查:版本、執行模式、設定目錄(無需啟動前端) |
GET /api/bootstrap | 一次拿到 themes_doc / settings / registry / platforms / 路徑 |
POST /api/render | 生成預覽,返回 {png: dataURL, path, theme, size, bytes} |
POST /api/save | 生成並寫入 output/,返回落盤路徑 |
POST /api/theme-preview | 未儲存主題草案 → 卡片 + 語義圖 + 貼紙條 + 可讀性診斷,不寫設定檔案 |
POST /api/schemes | 背景圖 → 多套配色方案。傳 {"path":"/abs/bg.jpg"} 或 {"image":"data:image/png;base64,..."} |
GET /api/schemes?image_id=xxx | 重新取已上傳圖片的方案 |
POST /api/config/themes | {"themes_doc": {...}} 儲存主題設定(有校驗) |
POST /api/config/settings | {"settings": {...}} 儲存全域設定 |
POST /api/config/reset | 恢復出廠主題(會覆蓋私有主題,先備份) |
POST /api/reveal | 開啟輸出資料夾 |
GET /api/sticker?id=book&theme=study | 貼紙圖示 PNG |
/api/render 與 /api/save 的請求體:
{
"title": "今天也要好好生活",
"subtitle": "把普通的日子過得響亮一點",
"platform": "xhs",
"theme": "auto",
"date": null,
"brand": "Claw · 每日一句",
"seed": null,
"bg_image_id": null,
"bg_path": "./bg.jpg",
"bg_scheme": 0,
"dark_override": null
}
bg_scheme可為整數序號或#RRGGBB;dark_override為true/false時強制淺/深卡片,null跟隨圖片判斷。bg_image_id由/api/schemes返回;也可以直接給bg_path服務端可訪問的路徑。- 返回的
png是data:image/png;base64,...,解碼後寫檔案即可。
範例(DAILY_CARD_URL 未設定時走本地):
DC_URL="${DAILY_CARD_URL:-http://127.0.0.1:8777}"
curl -s "$DC_URL/api/save" \
-H 'Content-Type: application/json' \
-d '{"title":"今天也要好好生活","subtitle":"把日子過得響亮一點","platform":"xhs"}' \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["path"])'
主題草案預覽 / 配色診斷(儲存前先驗貨)
想在寫入設定前判斷一套配色好不好看、文字讀不讀得清,調 /api/theme-preview。theme 是完整主題草稿,服務端只放記憶體:
{
"theme": {
"label": "MY THEME · 新主題",
"keywords": ["打卡"],
"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": "範例標題",
"subtitle": "範例副標題",
"platform": "moments",
"date": "2026-11-11",
"seed": 7
}
返回欄位(card / legend / stickers / sticker_sheet 均為 data:image/png;base64,...):
| 欄位 | 含義 |
|---|---|
card | 用這份草稿真實渲染出的卡片 |
legend | 語意化配色示意圖:真實紋樣 + 卡片層級 + 10 個顏色各管什麼 |
stickers | 已選貼紙在目前配色下的樣子 |
sticker_sheet | 全量貼紙 sprite,配合 sheet(cols/rows/cell/order)切片顯示 |
diagnostics | [{level: ok/warn/tip, text: 中文說明}] |
contrast | 各項對比度數值(ink_card / sub_card / pill_pair / card_bg / accent_bg / bg_light) |
motif / dark / draft_only | 紋樣中文名與說明、明暗標記、恆為 true 表示未落盤 |
diagnostics 按 WCAG 對比度檢查:主文字/副文字/標籤字可讀性、卡片與背景區分度、強調色是否夠跳、以及「背景很暗卻設成淺色主題」這類矛盾。推薦做法:先 POST 草稿看診斷 → 有 warn 就照提示改顏色再跑一次 → 沒有 warn 才調 /api/config/themes 儲存。
不啟動後台時可直接呼叫模組:
import base64, cardconfig as cfg, cardpreview as cp
draft = cfg.load_doc()["themes"]["study"] # 巢狀結構,含 colors
draft["colors"]["accent"] = "#C2185B" # 改一下看看
r = cp.build_preview({"theme": draft, "title": "範例", "subtitle": "副標題"})
for it in r["diagnostics"]:
print(it["level"], it["text"])
open("/tmp/draft-card.png", "wb").write(base64.b64decode(r["card"].split(",", 1)[1]))
更新與多端同步
唯一版本真相源是 git 倉庫,其餘各端都是派生,只單向流出:
| 端 | 更新方式 | 私有設定 |
|---|---|---|
| 本機 / 雲端伺服器 | git pull && ./install.sh | 不受影響,不會覆蓋 |
| 雲端伺服器前端靜態版本 | ./scripts/publish-web.sh,--rollback 可秒回滾 | 與 Python 服務解耦,不需重啟 |
| 本機 skill 註冊 | ./install.sh --link-skill 建符號連結,避免檔案副本漂移 | 不受影響 |
| skillhub 等平台快照 | 維護者打 tag 後重新匯入,天然有版本滯後 | 平台只拿到出廠範本 |
出廠範本 themes.default.json 隨版本更新,使用者私有的 themes.json 永不覆蓋。需要把新出廠主題合進自己的設定時,手動從 themes.default.json 拷貝對應條目,或在後台用「匯出 JSON → 合併 → 匯入」,不要直接執行 --init-config / /api/config/reset。
伺服器部署與 CI/CD 接入說明見 docs/DEPLOY.md。scripts/selfcheck.sh 共 8 步,包含前端路徑可移植性檢查與子路徑部署模擬(進程內起代理,不需要真的裝 nginx)。
Agent 推薦工作流
- 從使用者話裡提取標題、副標題(沒給副標題就補一句貼合語氣的短句,或留空)。
- 判斷平台:沒說就用
xhs;提到公眾號用wechat,朋友圈用moments。 - 若使用者給了背景圖:先
--list-schemes或/api/schemes看候選,選定後再生成;使用者沒指定就用方案 0。 - 執行 CLI(無需服務);只有使用者明確要用後台/遠端時才調
/api/save。 - 用 present_files 展示成品圖,回覆裡說明主題、尺寸、日期、取色方案。
- 使用者要改風格 → 改
config/themes.json或後台設定面板,不要改cardgen.py。
注意事項
- 程式碼分工:
cardgen.py只負責渲染,cardconfig.py負責設定載入/儲存/取色,cardpreview.py負責主題草案預覽與配色診斷,server.py是後台,都讀同一份config/*.json。 output/、uploads/、config/themes.json、config/settings.json、.env均被.gitignore忽略;examples/是 demo 成品圖(約 6.7 MB,不參與執行,可隨時刪除)。- 主題 ID 只允許字母數字
-_;顏色必須是#RRGGBB;貼紙 ID 必須存在於config/stickers.json。 - 圖片尺寸越大、超取樣越高越慢;預設 2x 超取樣已夠清晰。
server.py零鑑權且預設只監聽127.0.0.1。公開部署前務必加反向代理鑑權或 IP 白名單;雲端部署用--api-only只暴露 API,詳見docs/DEPLOY.md。- 原始碼裡不允許出現
src="/..."/href="/..."/"/api/..."這類域名根絕對路徑,selfcheck.sh會阻斷這類回歸;所有請求統一走url()。
已知限制 / 下一版本計畫
- 貼紙不能自訂上傳(目前版本):貼紙只能從
config/stickers.json已註冊的 28 個向量貼紙中選擇,沒有獨立的貼紙庫管理模組,也不支援上傳 PNG/SVG 當貼紙。要增加形狀,目前需開發者在cardgen.py新增s_xxx繪製函式並在stickers.json註冊。 - 下一版本計畫:自訂貼紙上傳(PNG/SVG,自動取色適配主題)、貼紙庫管理面板(增刪改 / 分組 / 預覽 / 重用)、貼紙與主題解耦。使用者已明確該項放到下一版本實現,本次不涉及。
- 主題草案預覽用的是 1x 超取樣以加快回應,與最終 2x 輸出在極細顆粒上略有差異,版式與配色一致。