Feishu Portfolio Launch
這個 Skill 做什麼
一句話:給我飛書多維表格連結,我把作品集網站搭出來,並把「飛書臨時連結會過期」這件事自動化處理掉。
預設交付物:
index.html或靜態前端頁面api/videos.jsonapi/covers.jsonapi/portfolio.jsonrefresh.py.github/workflows/refresh.yml- 帶動效的前端互動層(CSS / JS / Canvas / Three.js 均可)
內建模板資源:
目標結果:
- 網站部署在 GitHub Pages
- 飛書媒體連結由 GitHub Actions 每 12 小時自動重新整理
- 使用者不用保持自己的電腦開機
- 頁面不是純靜態排版,至少具備一套完整的入場 / 捲動 / 懸停 / 切頁動效
適用場景
✅ 適合:
- AI 影片 / 圖片作品集
- 攝影、設計、創意樣片庫
- 客戶案例展示站
- 任何「內容在飛書附件裡,前台只負責展示」的場景
❌ 不適合:
- 圖文部落格
- 電商、支付、登入系統
- 需要資料庫寫入和後端業務邏輯的網站
核心原則
不要把飛書臨時 URL 當成永久資源。
飛書附件的播放 / 下載位址會過期。正確做法不是讓使用者在本地電腦上定時跑腳本,而是:
- 從飛書多維表格讀取最新記錄
- 調用飛書 API 把附件
file_token解析成臨時 URL - 生成
api/*.json - 提交回 GitHub 倉庫
- 讓 GitHub Pages 自動重新部署
也就是:
Feishu Bitable -> refresh.py -> api/*.json -> GitHub Pages
執行流程
Step 0:環境檢查
先檢查本地是否具備初始化所需工具:
for cmd in node python3 gh git; do
which "$cmd" >/dev/null 2>&1 && echo "OK $cmd" || echo "MISS $cmd"
done
lark-cli --version >/dev/null 2>&1 && echo "OK lark-cli" || echo "MISS lark-cli"
gh auth status >/dev/null 2>&1 && echo "OK GitHub auth" || echo "MISS GitHub auth"
如果缺少工具,再讓使用者安裝。
如果 gh 沒登入,先完成 GitHub 登入。
Step 1:拿到飛書 Base 和正確的資料表
向使用者要飛書多維表格連結,例如:
https://my.feishu.cn/base/AbCdEfGhIjk
從 URL 裡解析出 app_token。
然後列出所有表:
lark-cli api GET "/open-apis/bitable/v1/apps/${APP_TOKEN}/tables"
不要預設選第一張表。
很多 Base 裡會同時存在「空模板表」和「真正有作品的素材表」。要繼續讀取記錄並驗證:
- 哪張表有真實附件欄位
- 哪張表記錄數正確
- 哪張表裡欄位名是使用者要展示的內容
優先找這些欄位:
- 影片欄位:
樣片/影片/附件 - 封面欄位:
封面/封面圖/海報/圖片 - 標題欄位:
內容/標題/作品名稱 - 分類欄位:
類型/分類 - 時長欄位:
時長 - 工具欄位:
AI工具/工具 - 排序欄位:
序號
如果一張表只有 文字 / 單選 / 日期 / 附件 這種空模板欄位,繼續換表,不要生成網站。
Step 2:驗證飛書權限
要讓 GitHub Actions 能自動重新整理,飛書應用必須至少能:
- 讀取多維表記錄
- 讀取附件媒體連結
執行方案裡要顯式依賴這 4 個 secrets:
LARK_APP_IDLARK_APP_SECRETLARK_BASE_TOKENLARK_TABLE_ID
如果使用者本機已經有可用的飛書應用配置,可以重複使用。否則要明確告訴使用者去飛書開放平台補權限和金鑰。
Step 3:匯出結構化作品資料
不要只提取 file_token 列表。
應構建一份前端可直接消費的結構化資料,至少包含:
- title
- categories
- duration
- tools
- order
- video_token
- cover_token
推薦輸出:
api/portfolio.json:完整作品陣列api/videos.json:video_token -> tmp_download_urlapi/covers.json:cover_token -> tmp_download_url
結構範例可直接參考倉庫內的 assets/portfolio.sample.json。
前端可以繼續用靜態 HTML + JS,也可以完全由 portfolio.json 渲染。
Step 4:生成前端頁面
預設生成靜態頁面,要求:
- 響應式作品網格
- 分類篩選
- 點擊卡片播放
- 全屏放大播放
- 只允許一個影片同時播放
- 封面優先使用飛書封面欄位,沒有封面時允許退化為無 poster
動效要求預設一起交付,不要只做「能打開」的靜態頁:
- 首螢幕至少有一組入場動畫,例如標題、說明、統計數字逐段 fade-up
- 導航在捲動後允許出現 blur / background / border 變化
- 卡片 hover 至少有一層輕量反饋,例如上浮、縮放、遮罩、標題變色
- 頁面切換或 section 切換應有過渡,不要突兀閃切
- About / 聯絡方式 / 能力模組這類資訊區,優先加 scroll reveal
- 如果使用者希望更強視覺表現,可以增加 Canvas 或 Three.js 背景動畫
實現邊界:
- 優先使用原生 CSS transition / keyframes / IntersectionObserver
- 需要持續運動背景時再用
requestAnimationFrame - 如果使用了 Three.js,必須確保移動端不會空白、卡死或遮擋主要內容
- 動畫不能影響影片播放、篩選、彈窗、移動端捲動和首螢幕可讀性
- 預設提供降級路徑,腳本失敗時文字和內容仍然可見
資料綁定原則:
- HTML 不要寫死過期 URL
- 頁面運行時拉取
/api/videos.json和/api/covers.json - 或者直接拉
/api/portfolio.json渲染卡片
如果使用者已有站點,優先保留現有視覺樣式,只替換資料來源和重新整理機制。
如果使用者明確提到參考現有站點風格,優先複用這些動畫類型:
- hero 文案入場
- sticky filter / nav 的捲動狀態過渡
- masonry 卡片 hover 動效
- 頁面淡入淡出切換
- About 頁的 stagger reveal
- 可選的 Three.js / Canvas 背景運動
Step 5:建立倉庫並部署 GitHub Pages
標準流程:
gh repo create <repo-name> --public --source=. --remote=origin --push
然後確認 Pages 來源是:
- branch:
main - path:
/
檢查:
gh api repos/<owner>/<repo>/pages
必須確認:
- Pages 已啟用
cname正常(如果有自訂網域)- source 指向
main和根目錄
Step 6:生成自動重新整理腳本
重新整理腳本應採用下面這條路線:
- 用
app_id + app_secret換tenant_access_token - 讀取 Bitable records
- 從記錄裡提取影片和封面附件 token
- 批次調用
batch_get_tmp_download_url - 寫入
api/videos.json、api/covers.json、api/portfolio.json
關鍵要求:
- 支援分頁讀取 records
- 批次請求按 5 個 token 一組
- 不要把 token 列表硬編碼在腳本裡
- 優先從真實表記錄動態生成
- 允許多種欄位名候選
建議檔案名稱:
refresh.py
優先直接複製 skill 自帶模板:
cp ~/.claude/skills/feishu-portfolio-launch/assets/refresh.py ./refresh.py
然後只修改欄位候選陣列,不要把具體 token 或具體 URL 硬編碼進去。
Step 7:生成 GitHub Actions Workflow
不要再使用本地 launchd 作為預設方案。
預設方案必須是 GitHub Actions。
工作流要求:
- 支援
workflow_dispatch - 支援
schedule,預設每 12 小時執行一次 - 執行
python refresh.py - 自動提交
api/videos.json、api/covers.json、api/portfolio.json
標準 secrets:
LARK_APP_IDLARK_APP_SECRETLARK_BASE_TOKENLARK_TABLE_ID
標準檔案:
.github/workflows/refresh.yml
優先直接複製 skill 自帶模板:
mkdir -p .github/workflows
cp ~/.claude/skills/feishu-portfolio-launch/assets/refresh.yml .github/workflows/refresh.yml
Step 8:把 Secrets 配進倉庫
如果當前環境已經有這些值,並且使用者明確讓你落地,就直接配置:
gh secret set LARK_APP_ID -R <owner>/<repo>
gh secret set LARK_APP_SECRET -R <owner>/<repo>
gh secret set LARK_BASE_TOKEN -R <owner>/<repo>
gh secret set LARK_TABLE_ID -R <owner>/<repo>
然後驗證:
gh secret list -R <owner>/<repo>
如果缺值,就停在這裡,明確告訴使用者缺哪個,不要偽造。
Step 9:手動觸發並驗證整條鏈路
完成配置後,立刻手動跑一次 workflow:
gh workflow run refresh.yml -R <owner>/<repo>
gh run list -R <owner>/<repo> --limit 3
gh run watch <run-id> -R <owner>/<repo> --exit-status
再檢查線上結果:
python3 - <<'PY'
import json, urllib.request, time
url = f'https://<domain-or-pages-url>/api/videos.json?t={int(time.time())}'
with urllib.request.urlopen(url, timeout=20) as r:
data = json.load(r)
print(data.get('_refreshed_at'))
print(data.get('_count'))
PY
然後抽測 1 條影片:
- 狀態碼應為
206或200 content-type應為video/mp4或可播放媒體類型
如果線上 api/videos.json 還是舊時間:
- 先看 Pages 部署是否完成
- 再看 workflow 是否真的提交了新 JSON
- 再確認 Pages source 是否指向正確分支和目錄
Step 10:網域綁定
如果使用者要自訂網域,再做:
CNAME檔案- GitHub Pages custom domain 設定
- DNS 配置引導
這部份沿用 GitHub Pages 標準流程,不需要和飛書邏輯耦合。
對使用者的預設解釋
遇到「網站能打開但影片播不了」,優先判斷:
api/videos.json是否還是舊的- 裡面的飛書 URL 是否已過期
- 自動重新整理 workflow 是否失敗
- Pages 是否還沒重新部署
預設不要先懷疑播放器,也不要先懷疑前端樣式。
如果使用者說「頁面太死」或者「想要像作品集一樣更有呼吸感」,預設增加動畫層,而不是只改顏色和排版。
成功標準
這個 Skill 完成後,至少要滿足:
- 網站已上線
- GitHub Pages 可訪問
- 影片可播放
- 倉庫裡有自動重新整理 workflow
- 倉庫裡已有 4 個
LARK_*secrets - 手動觸發 workflow 成功
- 線上
api/videos.json的_refreshed_at是新時間
不要再預設做的事
- 不要預設生成本地
launchd - 不要預設依賴使用者 Mac 長期開機
- 不要硬編碼所有
file_token - 不要只憑第一張表就繼續
- 不要只生成
videos.json,忽略封面和結構化記錄
參考實現
如果需要一個已經驗證過的做法,先直接複用 skill 倉庫自帶模板:
assets/refresh.pyassets/refresh.ymlassets/portfolio.sample.json
實際專案裡最終會生成這些檔案:
refresh.py.github/workflows/refresh.ymlapi/videos.jsonapi/covers.jsonapi/portfolio.json
優先複用現成倉庫模式,再按使用者站點樣式做適配。