Communitygithub.com

Ship portfolio — Base Feishu → GitHub Pages + Actions

Transformer une table Feishu en portfolio live sur GitHub Pages, avec Actions qui rafraîchissent les liens média temporaires. Pour créateurs dont les assets vivent dans Feishu — pas blogs, ecommerce ou backends write-back.

Qu'est-ce que Ship portfolio — Base Feishu → GitHub Pages + Actions ?

Personal websites étape 3 (ship) : feishu-portfolio-launch. SSOT Feishu → site → Pages + refresh planifié.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add Jane-xiaoer/feishu-portfolio-launch

Demander à votre IA préférée

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

Documentation

Lancement du Portfolio Feishu

Ce que fait cette compétence

En un mot : Donnez-moi un lien vers un tableau multi-dimensionnel Feishu, je construis un site de portfolio et j'automatise le problème des « liens temporaires Feishu qui expirent ».

Livrables par défaut :

  • index.html ou page front-end statique
  • api/videos.json
  • api/covers.json
  • api/portfolio.json
  • refresh.py
  • .github/workflows/refresh.yml
  • Couche interactive front-end avec animations (CSS / JS / Canvas / Three.js au choix)

Ressources de modèles intégrés :

Objectif final :

  • Site déployé sur GitHub Pages
  • Les liens médias Feishu sont automatiquement rafraîchis toutes les 12 heures via GitHub Actions
  • L'utilisateur n'a pas besoin de laisser son ordinateur allumé
  • La page n'est pas une mise en page purement statique ; elle a au moins un ensemble complet d'animations d'entrée / défilement / survol / transition de page

Cas d'utilisation

✅ Convient pour :

  • Portfolios de vidéos / images IA
  • Galeries d'échantillons de photographie, design, créativité
  • Sites de démonstration de cas clients
  • Tout scénario où « le contenu est dans les pièces jointes Feishu, le front-end se contente d'afficher »

❌ Ne convient pas pour :

  • Blogs avec texte et images
  • Systèmes de commerce électronique, de paiement, de connexion
  • Sites nécessitant une écriture en base de données et une logique métier back-end

Principes fondamentaux

Ne traitez pas les URL temporaires Feishu comme des ressources permanentes.

Les URL de lecture / téléchargement des pièces jointes Feishu expirent. La bonne approche n'est pas de faire exécuter un script programmé sur l'ordinateur local de l'utilisateur, mais plutôt :

  1. Lire les derniers enregistrements du tableau multi-dimensionnel Feishu
  2. Appeler l'API Feishu pour résoudre le file_token de la pièce jointe en URL temporaire
  3. Générer api/*.json
  4. Commit et push vers le dépôt GitHub
  5. Laisser GitHub Pages se redéployer automatiquement

Soit :

Feishu Bitable -> refresh.py -> api/*.json -> GitHub Pages


Processus d'exécution

Étape 0 : Vérification de l'environnement

Vérifiez d'abord si les outils nécessaires à l'initialisation sont disponibles localement :

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"

Si des outils manquent, demandez à l'utilisateur de les installer.
Si gh n'est pas connecté, terminez d'abord la connexion GitHub.


Étape 1 : Obtenir la Base Feishu et la table de données correcte

Demandez à l'utilisateur le lien du tableau multi-dimensionnel Feishu, par exemple :

https://my.feishu.cn/base/AbCdEfGhIjk

Extrayez app_token de l'URL.

Ensuite, listez toutes les tables :

lark-cli api GET "/open-apis/bitable/v1/apps/${APP_TOKEN}/tables"

Ne sélectionnez pas la première table par défaut.
De nombreuses Bases contiennent à la fois une « table de modèle vide » et une « table de matériel avec du vrai contenu ». Continuez à lire les enregistrements et à vérifier :

  • Quelle table a des champs de pièces jointes réelles
  • Quelle table a le bon nombre d'enregistrements
  • Quelle table a des noms de champs qui correspondent au contenu que l'utilisateur souhaite afficher

Cherchez d'abord ces champs :

  • Champ vidéo : échantillon / vidéo / pièce jointe
  • Champ couverture : couverture / image de couverture / affiche / image
  • Champ titre : contenu / titre / nom de l'œuvre
  • Champ catégorie : type / catégorie
  • Champ durée : durée
  • Champ outil : outil IA / outil
  • Champ tri : numéro

Si une table n'a que des champs de modèle vide comme texte / choix unique / date / pièce jointe, continuez à changer de table, ne générez pas de site.


Étape 2 : Vérifier les autorisations Feishu

Pour que GitHub Actions puisse se rafraîchir automatiquement, l'application Feishu doit au moins pouvoir :

  • Lire les enregistrements du tableau multi-dimensionnel
  • Lire les liens médias des pièces jointes

Le plan d'exécution doit dépendre explicitement de ces 4 secrets :

  • LARK_APP_ID
  • LARK_APP_SECRET
  • LARK_BASE_TOKEN
  • LARK_TABLE_ID

Si l'utilisateur a déjà une configuration d'application Feishu utilisable localement, elle peut être réutilisée. Sinon, il faut explicitement indiquer à l'utilisateur d'ajouter les autorisations et les clés sur la plateforme ouverte Feishu.


Étape 3 : Exporter les données structurées des œuvres

N'extrayez pas seulement une liste de file_token.
Construisez des données structurées directement consommables par le front-end, incluant au moins :

  • title
  • categories
  • duration
  • tools
  • order
  • video_token
  • cover_token

Sortie recommandée :

  • api/portfolio.json : tableau complet des œuvres
  • api/videos.json : video_token -> tmp_download_url
  • api/covers.json : cover_token -> tmp_download_url

Un exemple de structure est directement disponible dans assets/portfolio.sample.json du dépôt.

Le front-end peut continuer à utiliser du HTML + JS statique, ou être entièrement rendu à partir de portfolio.json.


Étape 4 : Générer la page front-end

Générez par défaut une page statique, avec les exigences suivantes :

  • Grille d'œuvres responsive
  • Filtrage par catégorie
  • Lecture au clic sur une carte
  • Lecture en plein écran agrandi
  • Un seul lecteur vidéo actif à la fois
  • Utilisez en priorité le champ de couverture Feishu ; s'il est absent, passez en mode sans poster

Les animations doivent être livrées par défaut, ne vous contentez pas d'une page statique « fonctionnelle » :

  • Au moins une animation d'entrée sur la première page, par exemple titre, description, chiffres statistiques qui apparaissent progressivement (fade-up)
  • La navigation doit permettre des changements de flou / fond / bordure après le défilement
  • Les cartes doivent avoir au moins un retour léger au survol, par exemple soulèvement, zoom, superposition, changement de couleur du titre
  • Les transitions de page ou de section doivent avoir des transitions, pas de coupures brusques
  • Les zones d'information comme À propos / Contact / Compétences doivent de préférence avoir un scroll reveal
  • Si l'utilisateur souhaite un rendu plus fort, ajoutez des animations de fond Canvas ou Three.js

Limites d'implémentation :

  • Privilégiez les transitions CSS natives / keyframes / IntersectionObserver
  • Utilisez requestAnimationFrame uniquement pour les arrière-plans en mouvement continu
  • Si Three.js est utilisé, assurez-vous qu'il ne cause pas de vide, de blocage ou de masquage du contenu principal sur mobile
  • Les animations ne doivent pas affecter la lecture vidéo, le filtrage, les fenêtres modales, le défilement mobile ou la lisibilité de la première page
  • Fournissez un chemin de repli par défaut : si le script échoue, le texte et le contenu doivent rester visibles

Principes de liaison des données :

  • Le HTML ne doit pas contenir d'URL expirées codées en dur
  • La page charge /api/videos.json et /api/covers.json à l'exécution
  • Ou charge directement /api/portfolio.json pour rendre les cartes

Si l'utilisateur a déjà un site existant, conservez en priorité son style visuel actuel et remplacez seulement la source de données et le mécanisme de rafraîchissement.

Si l'utilisateur mentionne explicitement vouloir se référer au style d'un site existant, privilégiez la réutilisation de ces types d'animations :

  • Animation d'entrée du texte hero
  • Transition de l'état de défilement pour le filtre / nav sticky
  • Animation au survol des cartes masonry
  • Transition de fondu enchaîné entre les pages
  • Dévoilement progressif (stagger reveal) de la section À propos
  • Mouvement de fond Three.js / Canvas optionnel

Étape 5 : Créer le dépôt et déployer GitHub Pages

Processus standard :

gh repo create <repo-name> --public --source=. --remote=origin --push

Ensuite, confirmez que la source de Pages est :

  • branch : main
  • path : /

Vérifiez :

gh api repos/<owner>/<repo>/pages

Assurez-vous que :

  • Pages est activé
  • cname est correct (s'il y a un nom de domaine personnalisé)
  • la source pointe vers main et le répertoire racine

Étape 6 : Générer le script de rafraîchissement automatique

Le script de rafraîchissement doit suivre ce chemin :

  1. Utiliser app_id + app_secret pour obtenir tenant_access_token
  2. Lire les enregistrements Bitable
  3. Extraire les tokens des pièces jointes vidéo et couverture des enregistrements
  4. Appeler batch_get_tmp_download_url en masse
  5. Écrire dans api/videos.json, api/covers.json, api/portfolio.json

Exigences clés :

  • Prend en charge la pagination de la lecture des enregistrements
  • Les requêtes en masse doivent être regroupées par lots de 5 tokens
  • Ne codez pas en dur la liste des tokens dans le script
  • Générez dynamiquement à partir des enregistrements réels de la table
  • Permettez plusieurs noms de champs candidats

Nom de fichier recommandé :

  • refresh.py

Copiez d'abord le modèle fourni par la compétence :

cp ~/.claude/skills/feishu-portfolio-launch/assets/refresh.py ./refresh.py

Ensuite, modifiez seulement les tableaux de noms de champs candidats. Ne codez pas en dur de token ou d'URL spécifique.


Étape 7 : Générer le workflow GitHub Actions

N'utilisez plus launchd local comme solution par défaut.
La solution par défaut doit être GitHub Actions.

Exigences du workflow :

  • Prend en charge workflow_dispatch
  • Prend en charge schedule, par défaut toutes les 12 heures
  • Exécute python refresh.py
  • Commit et push automatiquement api/videos.json, api/covers.json, api/portfolio.json

Secrets standard :

  • LARK_APP_ID
  • LARK_APP_SECRET
  • LARK_BASE_TOKEN
  • LARK_TABLE_ID

Fichier standard :

  • .github/workflows/refresh.yml

Copiez d'abord le modèle fourni par la compétence :

mkdir -p .github/workflows
cp ~/.claude/skills/feishu-portfolio-launch/assets/refresh.yml .github/workflows/refresh.yml

Étape 8 : Configurer les Secrets dans le dépôt

Si l'environnement actuel a déjà ces valeurs, et que l'utilisateur vous demande explicitement de les mettre en place, configurez directement :

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>

Ensuite, vérifiez :

gh secret list -R <owner>/<repo>

Si des valeurs manquent, arrêtez-vous ici et dites explicitement à l'utilisateur ce qui manque. Ne falsifiez rien.


Étape 9 : Déclencher manuellement et vérifier toute la chaîne

Après avoir terminé la configuration, déclenchez immédiatement le workflow une fois manuellement :

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

Ensuite, vérifiez le résultat en ligne :

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

Ensuite, testez un échantillon d'une vidéo :

  • Le code de statut doit être 206 ou 200
  • Le content-type doit être video/mp4 ou un type de média lisible

Si api/videos.json en ligne a encore l'ancienne heure :

  • Vérifiez d'abord si le déploiement Pages est terminé
  • Ensuite, vérifiez si le workflow a vraiment commit le nouveau JSON
  • Ensuite, confirmez que la source Pages pointe vers la branche et le répertoire corrects

Étape 10 : Liaison de domaine

Si l'utilisateur veut un nom de domaine personnalisé, faites ceci :

  • Fichier CNAME
  • Paramètre du domaine personnalisé GitHub Pages
  • Configuration DNS guidée

Cette partie suit le processus standard GitHub Pages et n'a pas besoin d'être couplée à la logique Feishu.


Explication par défaut pour l'utilisateur

Face à « le site s'ouvre mais la vidéo ne se lit pas », déterminez d'abord :

  1. Si api/videos.json est encore ancien
  2. Si l'URL Feishu qu'il contient a expiré
  3. Si le workflow de rafraîchissement automatique a échoué
  4. Si Pages n'a pas encore été redéployé

Par défaut, ne suspectez pas d'abord le lecteur, ni le style front-end.

Si l'utilisateur dit « la page est trop figée » ou « je veux plus de vie, comme un portfolio », ajoutez une couche d'animation par défaut, ne vous contentez pas de changer les couleurs et la mise en page.


Critères de succès

Après avoir terminé cette compétence, au moins ces conditions doivent être remplies :

  • Site en ligne
  • GitHub Pages accessible
  • Vidéos lisibles
  • Workflow de rafraîchissement automatique dans le dépôt
  • 4 secrets LARK_* déjà dans le dépôt
  • Déclenchement manuel du workflow réussi
  • _refreshed_at dans api/videos.json en ligne est une heure récente

Ce qu'il ne faut plus faire par défaut

  • Ne générez plus de launchd local par défaut
  • Ne dépendez plus du Mac de l'utilisateur allumé en permanence par défaut
  • Ne codez plus en dur tous les file_token
  • Ne continuez plus seulement avec la première table
  • Ne générez plus seulement videos.json en ignorant les couvertures et les enregistrements structurés

Implémentation de référence

Si vous avez besoin d'une approche déjà validée, réutilisez d'abord directement les modèles du dépôt de la compétence :

  • assets/refresh.py
  • assets/refresh.yml
  • assets/portfolio.sample.json

Dans un projet réel, ces fichiers seront finalement générés :

  • refresh.py
  • .github/workflows/refresh.yml
  • api/videos.json
  • api/covers.json
  • api/portfolio.json

Réutilisez d'abord le modèle de dépôt existant, puis adaptez-le au style du site de l'utilisateur.

Skills associés