Feishu Portfolio Launch
이 Skill의 기능
한 마디로 말하면: Feishu 다차원 테이블 링크를 주면, 포트폴리오 웹사이트를 구축하고 'Feishu 임시 링크 만료' 문제를 자동화하여 처리합니다.
기본 인도물:
index.html또는 정적 프론트엔드 페이지api/videos.jsonapi/covers.jsonapi/portfolio.jsonrefresh.py.github/workflows/refresh.yml- 애니메이션이 적용된 프론트엔드 상호작용 레이어 (CSS / JS / Canvas / Three.js 모두 가능)
내장 템플릿 리소스:
목표 결과:
- GitHub Pages에 웹사이트 배포
- Feishu 미디어 링크는 GitHub Actions에 의해 12시간마다 자동으로 새로고침
- 사용자가 자신의 컴퓨터를 켜둘 필요 없음
- 페이지는 단순 정적 레이아웃이 아니며, 최소한 완전한 진입 / 스크롤 / 호버 / 페이지 전환 애니메이션 세트를 갖춤
적용 시나리오
✅ 적합:
- AI 비디오 / 이미지 포트폴리오
- 사진, 디자인, 크리에이티브 샘플 라이브러리
- 고객 사례 소개 사이트
- '콘텐츠는 Feishu 첨부 파일에 있고, 프론트엔드는 표시만 담당'하는 모든 시나리오
❌ 부적합:
- 텍스트/이미지 블로그
- 전자상거래, 결제, 로그인 시스템
- 데이터베이스 쓰기 및 백엔드 비즈니스 로직이 필요한 웹사이트
핵심 원칙
Feishu 임시 URL을 영구 리소스로 간주하지 마십시오.
Feishu 첨부 파일의 재생/다운로드 주소는 만료됩니다. 올바른 방법은 사용자가 로컬 컴퓨터에서 정기적으로 스크립트를 실행하도록 하는 것이 아니라:
- Feishu 다차원 테이블에서 최신 레코드 읽기
- Feishu 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: Feishu Base와 올바른 데이터 테이블 찾기
사용자에게 Feishu 다차원 테이블 링크를 요청합니다. 예:
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: Feishu 권한 확인
GitHub Actions가 자동으로 새로고침하려면 Feishu 앱이 최소한 다음 작업을 수행할 수 있어야 합니다:
- 다차원 테이블 레코드 읽기
- 첨부 파일 미디어 링크 읽기
실행 계획에서 다음 4개의 secrets에 명시적으로 의존해야 합니다:
LARK_APP_IDLARK_APP_SECRETLARK_BASE_TOKENLARK_TABLE_ID
사용자 로컬에 이미 사용 가능한 Feishu 앱 구성이 있으면 재사용할 수 있습니다. 그렇지 않으면 사용자에게 Feishu Open Platform에서 권한과 키를 추가하도록 명확히 알려야 합니다.
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: 프론트엔드 페이지 생성
기본적으로 정적 페이지를 생성하며, 다음을 요구합니다:
- 반응형 작품 그리드
- 카테고리 필터링
- 카드 클릭 시 재생
- 전체 화면 확대 재생
- 한 번에 하나의 비디오만 재생 허용
- 커버는 Feishu 커버 필드를 우선 사용하고, 커버가 없으면 poster 없이 폴백 허용
애니메이션 효과는 기본적으로 함께 제공되어야 하며, 단순히 '열 수 있는' 정적 페이지만 제공하지 마십시오:
- 첫 화면에는 최소한 하나의 진입 애니메이션 세트가 있어야 합니다. 예: 제목, 설명, 통계 숫자가 fade-up으로 순차적으로 나타남
- 내비게이션은 스크롤 후 blur / background / border 변경을 허용
- 카드 hover에는 최소한 한 가지 가벼운 피드백이 있어야 합니다. 예: 떠오름, 확대, 오버레이, 제목 색상 변경
- 페이지 전환 또는 섹션 전환에는 트랜지션이 있어야 하며, 갑작스러운 깜빡임 전환 금지
- 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 애니메이션
- 페이지 fade-in/fade-out 전환
- 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 사용자 정의 도메인 설정
- DNS 구성 안내
이 부분은 GitHub Pages 표준 절차를 따르며 Feishu 로직과 결합할 필요가 없습니다.
사용자를 위한 기본 설명
'웹사이트는 열리지만 비디오가 재생되지 않는' 경우, 우선 판단:
api/videos.json이 여전히 오래된 것인가- 내부 Feishu 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
기존 저장소 패턴을 우선 재사용한 다음 사용자 사이트 스타일에 맞게 조정하십시오.