Lanzamiento de Portafolio en Feishu
¿Qué hace esta Skill?
En una frase: Dame el enlace de tu tabla multidimensional de Feishu, construyo el sitio de portafolio y automatizo que los enlaces temporales de Feishu expiren.
Entregables por defecto:
index.htmlo página frontend estáticaapi/videos.jsonapi/covers.jsonapi/portfolio.jsonrefresh.py.github/workflows/refresh.yml- Capa de interacción frontend con animaciones (CSS / JS / Canvas / Three.js)
Recursos de plantilla integrados:
Objetivo:
- Sitio desplegado en GitHub Pages
- Los enlaces multimedia de Feishu se actualizan automáticamente cada 12 horas mediante GitHub Actions
- El usuario no necesita mantener su computadora encendida
- La página no es solo estática: incluye al menos un conjunto completo de animaciones de entrada, desplazamiento, hover y transición
Escenarios de uso
✅ Adecuado para:
- Portafolios de videos/imágenes con IA
- Galerías de fotografía, diseño y muestras creativas
- Sitios de demostración de casos de clientes
- Cualquier escenario donde "el contenido está en archivos adjuntos de Feishu y el frontend solo muestra"
❌ No adecuado para:
- Blogs con texto e imágenes
- Sistemas de comercio electrónico, pagos o inicio de sesión
- Sitios que requieren escritura en base de datos y lógica de backend
Principio central
No trates las URLs temporales de Feishu como recursos permanentes.
Las URLs de reproducción/descarga de archivos adjuntos de Feishu caducan. La solución correcta no es que el usuario ejecute un script periódicamente en su computadora local, sino:
- Leer los registros más recientes de la tabla multidimensional de Feishu
- Llamar a la API de Feishu para convertir el
file_tokendel adjunto en una URL temporal - Generar
api/*.json - Enviar de vuelta al repositorio de GitHub
- Hacer que GitHub Pages se redespliegue automáticamente
Es decir:
Feishu Bitable -> refresh.py -> api/*.json -> GitHub Pages
Flujo de ejecución
Paso 0: Verificación del entorno
Primero verifica que las herramientas necesarias para la inicialización estén disponibles localmente:
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 falta alguna herramienta, pide al usuario que la instale.
Si gh no está autenticado, completa el inicio de sesión en GitHub.
Paso 1: Obtener el Base de Feishu y la tabla de datos correcta
Pide al usuario el enlace de la tabla multidimensional de Feishu, por ejemplo:
https://my.feishu.cn/base/AbCdEfGhIjk
Extrae el app_token de la URL.
Luego lista todas las tablas:
lark-cli api GET "/open-apis/bitable/v1/apps/${APP_TOKEN}/tables"
No selecciones la primera tabla por defecto. Muchos Bases contienen simultáneamente "tablas de plantilla vacía" y "tablas de materiales con obras reales". Continúa leyendo los registros y verifica:
- ¿Qué tabla tiene campos de archivos adjuntos reales?
- ¿Qué tabla tiene el número correcto de registros?
- ¿Qué tabla tiene nombres de campo que el usuario quiere mostrar?
Prioriza buscar estos campos:
- Campo de video:
Muestra/Video/Adjunto - Campo de portada:
Portada/Imagen de portada/Póster/Imagen - Campo de título:
Contenido/Título/Nombre de la obra - Campo de categoría:
Tipo/Categoría - Campo de duración:
Duración - Campo de herramienta:
Herramienta de IA/Herramienta - Campo de orden:
Número de orden
Si una tabla solo tiene campos de plantilla vacía como Texto / Selección única / Fecha / Adjunto, sigue cambiando de tabla, no generes el sitio.
Paso 2: Verificar los permisos de Feishu
Para que GitHub Actions pueda actualizarse automáticamente, la aplicación de Feishu debe poder al menos:
- Leer los registros de la tabla multidimensional
- Leer los enlaces multimedia de los archivos adjuntos
El plan de ejecución debe depender explícitamente de estos 4 secretos:
LARK_APP_IDLARK_APP_SECRETLARK_BASE_TOKENLARK_TABLE_ID
Si el usuario ya tiene una configuración de aplicación de Feishu utilizable localmente, se puede reutilizar. De lo contrario, se debe indicar claramente que vaya a la plataforma abierta de Feishu para agregar permisos y claves.
Paso 3: Exportar datos estructurados de las obras
No solo extraigas una lista de file_token.
Construye un conjunto de datos estructurados que el frontend pueda consumir directamente, que incluya al menos:
- title
- categories
- duration
- tools
- order
- video_token
- cover_token
Salida recomendada:
api/portfolio.json: Array completo de obrasapi/videos.json:video_token -> tmp_download_urlapi/covers.json:cover_token -> tmp_download_url
La estructura de ejemplo se puede consultar directamente en assets/portfolio.sample.json del repositorio.
El frontend puede seguir usando HTML + JS estático, o renderizarse completamente desde portfolio.json.
Paso 4: Generar la página frontend
Genera una página estática por defecto, que debe cumplir:
- Cuadrícula de obras responsiva
- Filtro por categoría
- Reproducción al hacer clic en la tarjeta
- Reproducción en pantalla completa ampliada
- Permitir que solo se reproduzca un video a la vez
- Portada: usar preferentemente el campo de portada de Feishu; si no hay portada, permitir degradación sin póster
Los efectos de animación deben entregarse juntos por defecto, no solo una página estática que "se pueda abrir":
- La pantalla de inicio debe tener al menos un conjunto de animaciones de entrada, como título, descripción, números estadísticos que aparecen gradualmente con fade-up
- La navegación debe permitir cambios en blur / background / border al desplazarse
- Las tarjetas deben tener al menos una retroalimentación ligera en hover, como elevación, escala, máscara, cambio de color de título
- Las transiciones entre páginas o secciones deben ser suaves, no cambios bruscos
- Las secciones de información como Acerca de / Contacto / Habilidades deben tener preferentemente scroll reveal
- Si el usuario desea una representación visual más intensa, se pueden agregar animaciones de fondo con Canvas o Three.js
Límites de implementación:
- Priorizar el uso de transiciones CSS nativas / keyframes / IntersectionObserver
- Usar
requestAnimationFramesolo cuando se necesite un movimiento de fondo continuo - Si se usa Three.js, asegurar que no haya espacios en blanco, bloqueos o que oculte el contenido principal en dispositivos móviles
- Las animaciones no deben afectar la reproducción de video, el filtrado, las ventanas emergentes, el desplazamiento en móviles ni la legibilidad de la pantalla de inicio
- Proporcionar una ruta de degradación por defecto: si el script falla, el texto y el contenido deben seguir siendo visibles
Principios de vinculación de datos:
- No codificar URLs caducadas en el HTML
- La página debe obtener
/api/videos.jsony/api/covers.jsonen tiempo de ejecución - O bien, obtener directamente
/api/portfolio.jsonpara renderizar las tarjetas
Si el usuario ya tiene un sitio existente, priorizar mantener el estilo visual actual y solo reemplazar la fuente de datos y el mecanismo de actualización.
Si el usuario menciona explícitamente que quiere referenciar el estilo de un sitio existente, priorizar reutilizar estos tipos de animación:
- Animación de entrada del texto hero
- Transición de estado de desplazamiento del filtro / navegación sticky
- Efecto hover de tarjetas en masonry
- Transición de fundido de páginas
- Revelación escalonada en la sección Acerca de
- Movimiento de fondo opcional con Three.js / Canvas
Paso 5: Crear el repositorio y desplegar GitHub Pages
Flujo estándar:
gh repo create <repo-name> --public --source=. --remote=origin --push
Luego confirma que la fuente de Pages sea:
- branch:
main - path:
/
Verifica:
gh api repos/<owner>/<repo>/pages
Debe confirmar:
- Pages está habilitado
cnamees correcto (si hay dominio personalizado)- source apunta a
mainy al directorio raíz
Paso 6: Generar el script de actualización automática
El script de actualización debe seguir esta ruta:
- Obtener
tenant_access_tokenconapp_id + app_secret - Leer los registros de Bitable
- Extraer los tokens de archivos adjuntos de video y portada de los registros
- Llamar a
batch_get_tmp_download_urlen lotes - Escribir
api/videos.json,api/covers.json,api/portfolio.json
Requisitos clave:
- Soporte para paginación al leer registros
- Solicitudes en lotes agrupando 5 tokens
- No codificar la lista de tokens en el script
- Generar dinámicamente desde los registros reales de la tabla
- Permitir múltiples nombres de campo candidatos
Nombre de archivo recomendado:
refresh.py
Priorizar copiar directamente la plantilla incluida en la skill:
cp ~/.claude/skills/feishu-portfolio-launch/assets/refresh.py ./refresh.py
Luego solo modificar el array de campos candidatos, sin codificar tokens o URLs específicos.
Paso 7: Generar el flujo de trabajo de GitHub Actions
Ya no uses launchd local como plan por defecto.
El plan por defecto debe ser GitHub Actions.
El flujo de trabajo debe:
- Soportar
workflow_dispatch - Soportar
schedule, por defecto ejecutar cada 12 horas - Ejecutar
python refresh.py - Confirmar automáticamente
api/videos.json,api/covers.json,api/portfolio.json
Secretos estándar:
LARK_APP_IDLARK_APP_SECRETLARK_BASE_TOKENLARK_TABLE_ID
Archivo estándar:
.github/workflows/refresh.yml
Priorizar copiar directamente la plantilla incluida en la skill:
mkdir -p .github/workflows
cp ~/.claude/skills/feishu-portfolio-launch/assets/refresh.yml .github/workflows/refresh.yml
Paso 8: Configurar los Secretos en el repositorio
Si el entorno actual ya tiene estos valores y el usuario te indica explícitamente que los concretes, configúralos directamente:
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>
Luego verifica:
gh secret list -R <owner>/<repo>
Si falta algún valor, detente aquí e indica claramente al usuario cuál falta, no lo inventes.
Paso 9: Activar manualmente y verificar toda la cadena
Después de la configuración, ejecuta manualmente el flujo de trabajo una vez:
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
Luego verifica el resultado en línea:
python3 - <<'PY'
import json, urllib.request, time
url = f'https://<dominio-o-url-pages>/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
Luego prueba una muestra de 1 video:
- El código de estado debe ser
206o200 content-typedebe servideo/mp4o un tipo de medio reproducible
Si el api/videos.json en línea aún tiene la hora anterior:
- Primero verifica si el despliegue de Pages se ha completado
- Luego verifica si el flujo de trabajo realmente confirmó el nuevo JSON
- Luego confirma si la fuente de Pages apunta a la rama y directorio correctos
Paso 10: Vinculación de dominio
Si el usuario quiere un dominio personalizado, hazlo:
- Archivo
CNAME - Configuración de dominio personalizado de GitHub Pages
- Guía de configuración de DNS
Esta parte sigue el flujo estándar de GitHub Pages, no necesita estar acoplada a la lógica de Feishu.
Explicación predeterminada para el usuario
Cuando te encuentres con "el sitio se abre pero el video no se reproduce", prioriza juzgar:
- ¿
api/videos.jsonsigue siendo antiguo? - ¿La URL de Feishu dentro ha caducado?
- ¿El flujo de trabajo de actualización automática falló?
- ¿Pages aún no se ha redesplegado?
Por defecto, no sospeches primero del reproductor ni del estilo del frontend.
Si el usuario dice "la página está muy muerta" o "quiero que tenga más vida como un portafolio", agrega una capa de animación por defecto, no solo cambies colores y tipografía.
Criterios de éxito
Una vez completada esta Skill, al menos debe cumplir:
- El sitio ya está en línea
- GitHub Pages es accesible
- Los videos se pueden reproducir
- El repositorio tiene un flujo de trabajo de actualización automática
- El repositorio ya tiene los 4 secretos
LARK_* - La activación manual del flujo de trabajo fue exitosa
- El
_refreshed_atdeapi/videos.jsonen línea muestra la hora actualizada
Lo que ya no se debe hacer por defecto
- No generar
launchdlocal por defecto - No depender de que el Mac del usuario esté encendido permanentemente
- No codificar todos los
file_token - No continuar solo con la primera tabla
- No generar solo
videos.json, ignorando portadas y registros estructurados
Implementación de referencia
Si necesitas un enfoque ya verificado, reutiliza directamente las plantillas incluidas en el repositorio de la skill:
assets/refresh.pyassets/refresh.ymlassets/portfolio.sample.json
En el proyecto real, finalmente se generarán estos archivos:
refresh.py.github/workflows/refresh.ymlapi/videos.jsonapi/covers.jsonapi/portfolio.json
Prioriza reutilizar el patrón del repositorio existente, luego adapta según el estilo del sitio del usuario.