Parallax Landing Page은(는) 무엇을 하나요?
짧은 동영상을 하나의 화면으로 구성된 시네마틱 랜딩 페이지로 변환합니다. 사용자가 스크롤 제스처를 통해 동영상 프레임을 프레임별로 탐색하며, 5개의 드라마틱한 텍스트 장면이 교차 페이드됩니다. 문서 자체는 실제로 스크롤되지 않으며 — 휠/터치/키보드 입력이 JavaScript에서 가로채져 가상 프레임 진행률로 변환됩니다.
이 스킬은 ../../examples/parasites/에 번들로 포함된 참조(이 정확한 스킬로 구축된 세 개의 작동 페이지 — github / lion / hope 랜딩)에서 입증된 패턴을 인코딩합니다. 여기에 모호한 부분이 있으면 해당 폴더를 진실의 원천으로 취급하십시오.
YUV.AI 피라미드에서 이 스킬의 위치
parallax-landing-page는 yuv-design-system, yuv-decks, yuv-viral-video, video-to-landing-page와 함께 YUV.AI 스킬 피라미드의 중간 계층에 있습니다. 최상위 오케스트레이터 yuv-pilot은 5–15초 동영상 클립을 단일 히어로 스크롤-스크럽 랜딩으로 만들어야 할 때마다 여기로 라우팅합니다.
이 스킬은 자체 시각적 언어(Anton + Caveat + Inter, 골드/앰버/액센트/크림 악센트 팔레트)를 사용하며 — yuv-design-system을 호출하지 않습니다. 두 시스템은 공존합니다: yuv-design-system은 웹/앱/데크 전반의 브랜드 팔레트를 소유하고, parallax-landing-page는 특히 시네마틱 스크롤-스크럽 미학을 소유합니다. YUV.AI parallax 랜딩의 경우, 선택적으로 푸터 영역에 브랜드 통일성을 위해 피닉스 워터마크 + 표준 Linktree URL을 추가할 수 있습니다 — 워터마크 파일은 yuv-design-system/assets/를 참조하십시오. 디자인 시스템의 네온 팔레트로 Anton/Caveat 폰트 스택을 교체하지 마십시오 — 시그니처 룩을 잃게 됩니다.
구축하는 것
각 랜딩은 다음과 같은 단일 고정 뷰포트입니다:
- 화면을 가득 채우는 캔버스, 한 번에 한 프레임씩 그리기(cover-fit, DPR ≤ 2)
- 5개의 절대 위치 텍스트 장면(킥커 + 대문자 Anton 헤드라인 + Caveat 손글씨 줄), 각각 고유의 스크롤 진행률 창이 있음
PARALLAX // showcase로고와 형제 랜딩으로의 링크를 포함한 고정 내비게이션- 사용자가 상호작용하기 전에 모든 프레임을 미리 로드하는 로더
- 비네트 + 필름 그레인 오버레이
- 사용자가 스크롤을 시작하면 사라지는 하단 스크롤 힌트
- 하단 우측 프레임 카운터 (예:
073 / 145) - CTA 섹션인 최종 장면 — 아래에 별도의
.end섹션 없음
q:v 2에서 총 무게: 프레임당 약 120–220 KB × 프레임 수. 6초 24fps 클립 = 145 프레임 ≈ 25 MB. 10초 클립 = 241 프레임 ≈ 53 MB.
저장 위치
기본: ~/Documents/yuv-projects/landings/<slug>/ — 항상 독립형 랜딩을 여기에 저장하여 다시 찾을 수 있도록 합니다. 사용자가 명시적으로 다른 위치를 선택하거나 또는 모드 B(기존 examples/parasites/ 쇼케이스에 통합)가 선택된 경우에만 재정의합니다.
mkdir -p ~/Documents/yuv-projects/landings
cd ~/Documents/yuv-projects/landings
# 스킬이 프레임을 추출하고 HTML을 구축하면서 여기에 <slug>/를 생성합니다.
최종 경로 (모드 A — 독립형): ~/Documents/yuv-projects/landings/<slug>/.
최종 경로 (모드 B — 통합): 사용자가 선택한 기존 쇼케이스 디렉토리.
모든 빌드가 끝나면 사용자에게 최종 경로를 알려주십시오.
워크플로우
네 가지 단계가 있습니다. 단계를 건너뛰지 마십시오 — 각 단계는 다음 단계를 위한 입력을 제공합니다.
1단계 — Discover (발견)
사용자와 다음을 확인합니다:
- 비디오 경로 — 소스 MP4 파일이 있는 위치.
- Slug — 짧은 폴더/파일 이름 (예:
hope,marcus,desk). 한 단어, 소문자, 공백 없음. 이것은 프레임 폴더 이름(<slug>/)과 HTML 파일 이름(<slug>.html)이 됩니다. - 테마 / 주제 — 이 랜딩은 무엇에 관한 것입니까? 제품 출시? 개인적인 순간? 야생 동물 조우? 카피를 작성하려면 이것이 필요합니다.
- 프로젝트 모드 — 독립형(새 폴더) 또는
examples/parasites/(이 저장소 최상위)의 기존 쇼케이스에 통합. 사용자가 "쇼케이스에 추가"라고 말하면 아래 모드 B를 의미합니다. - 악센트 색상 — 스크립트/CTA 하이라이트용:
gold(#f5b042),amber(#ff8a3d),accent(핑크 #ff4d6d),cream(#f5e9d4), 또는 새로운 색상 (:root에 추가하고style.css에 새로운.script.<name>규칙을 작성).
사용자가 이 중 일부를 지정하지 않은 경우, 기본값을 제안하고 계속 진행하십시오 — 결과를 보고 나서 답할 수 있는 질문에 멈추지 마십시오.
2단계 — Extract frames (프레임 추출)
번들 추출 스크립트를 실행합니다. ffprobe로 비디오를 검사하고 모든 프레임을 -q:v 2(거의 무손실 JPEG)로 네이티브 해상도로 추출하며, 이름을 frame-001.jpg에서 frame-NNN.jpg(3자리 제로 패딩)로 지정합니다.
python <skill>/scripts/extract_frames.py <video_path> <output_folder>
예시:
python C:/Users/User/.claude/skills/parallax-landing-page/scripts/extract_frames.py \
C:/Users/User/Documents/parasites/hope/hope.mp4 \
C:/Users/User/Documents/parasites/hope
스크립트는 JSON 메타데이터 블록을 stdout으로 출력합니다. 캡처하십시오 — HTML에 frame_count와 suggested_scroll_budget이 필요합니다.
-q:v 2를 사용하는 이유: ezgif 및 유사 도구는 공격적으로 재압축합니다(~55 KB/프레임). q:v 2의 네이티브 ffmpeg는 동일한 해상도에서 약 120–220 KB/프레임을 제공합니다 — 눈에 띄게 선명합니다. 다운스케일하지 마십시오; 절대 업스케일하지 마십시오(세부 사항 추가 없이 파일만 부풀립니다).
스크롤 예산 공식(프레임당 약 26px)을 사용하는 이유: 클립 길이에 관계없이 "진행된 프레임당 스크롤 픽셀"을 일정하게 유지합니다. 145 프레임 → ~4200, 241 프레임 → ~6300, 90 프레임 → ~2500(최소). 스크립트가 이를 계산하여 [2500, 8000] 범위로 고정합니다.
3단계 — Author the page (페이지 작성)
<skill>/assets/landing-page-template.html에 있는 템플릿을 읽습니다. 이것은 {{PLACEHOLDER}} 마커와 창의적인 부분 옆에 <!-- TODO: --> 주석이 있는 완전한 작동 파일입니다. 모든 것을 대체하여 <target>/<slug>.html에 새 파일을 작성합니다.
대체 체크리스트 (모든 플레이스홀더를 교체해야 함):
| 플레이스홀더 | 넣을 내용 | 예시 |
|---|---|---|
{{PAGE_TITLE}} | HTML <title> | Hope — The Fastest Heart in the Negev |
{{PAGE_DESCRIPTION}} | 메타 설명, 한 문장 | A moment with Hope, the cheetah of Midbarium. |
{{SLUG}} | 폴더 이름 (경로 없음, 슬래시 없음) | hope |
{{FRAME_COUNT}} | 정수 프레임 수 | 241 |
{{FRAME_COUNTER_TEXT}} | 일치하는 너비의 001 / NNN | 001 / 241 |
{{SCROLL_BUDGET}} | 추출기 JSON의 정수 | 6300 |
{{PREVIEW_FRAME_MID}} | 제로 패딩된 중간 프레임 | 121 |
{{PREVIEW_FRAME_END}} | 제로 패딩된 마지막 프레임 | 241 |
{{LOADER_TITLE}} | 한 단어, 대문자 | HOPE |
{{LOADER_SCRIPT}} | …로 끝나는 손글씨 줄 | summoning the runner… |
{{NAV_LINKS_HTML}} | 내비게이션용 전체 <a> 태그 블록 | 아래 참조 |
{{SCENE_N_*}} | 각 5개 장면의 킥커, 헤드라인, 손글씨 줄 | 카피 가이드 참조 |
{{SCROLL_HINT_TEXT}} | 2–4단어 대문자 프롬프트 | SCROLL TO RUN |
{{CTA_BUTTONS_HTML}} | 2–4개의 <a class="cta"> 태그 | 아래 참조 |
{{ACCENT_CLASS}} | .script.X 및 .cta.X용 악센트 색상 접미사 | amber |
시네마틱 카피 패턴(킥커 표현, 헤드라인 길이, 손글씨 줄 어조)에 대해서는 references/copy-guide.md를 읽으십시오. 이 스킬의 가치는 카피에서 나옵니다 — 일반적인 카피는 아름다운 애니메이션을 망칠 것입니다.
4단계 — Wire up assets (에셋 연결)
대상 폴더에 이미 style.css와 parallax.js가 있는 경우(쇼케이스 통합), 아무것도 하지 마십시오 — 공유됩니다. 그렇지 않으면 <skill>/assets/에서 대상 폴더로 둘 다 복사합니다:
cp <skill>/assets/style.css <target>/style.css
cp <skill>/assets/parallax.js <target>/parallax.js
기존 쇼케이스에 통합하는 경우 references/showcase-integration.md의 단계도 수행하십시오 — index.html에 카드 추가, 모든 기존 랜딩의 내비게이션 바에 링크 추가, 이전 랜딩의 최종 장면에 연결 CTA 추가.
사용자에게 보는 방법을 알려줍니다:
상위 폴더에서
python -m http.server 8000을 통해<target>/<slug>.html을 엽니다 (file://사용하지 마십시오 — Chromium이 로컬 이미지 출처로 캔버스를 오염시킬 수 있습니다).
파일 구조
<target>/
├── <slug>/ # 프레임 폴더
│ ├── <slug>.mp4 # 소스 (보존됨)
│ ├── frame-001.jpg
│ ├── frame-002.jpg
│ └── … frame-NNN.jpg
├── <slug>.html # 랜딩 페이지
├── style.css # 공유 (독립형인 경우 복사)
├── parallax.js # 공유 (독립형인 경우 복사)
└── index.html # 허브 (독립형이거나 통합인 경우에만)
프레임 폴더 이름과 HTML 파일 이름은 동일한 slug를 공유해야 합니다 — 페이지의 new ParallaxPage({folder: '<slug>', ...}) 호출에서 folder 옵션은 리터럴 폴더 경로입니다.
ParallaxPage API (이미 parallax.js에 있음, 재정의하지 마십시오)
new ParallaxPage({
folder: '<slug>', // frame-001.jpg 등을 포함하는 폴더
frameCount: 145, // 정수
prefix: 'frame-', // 이 스킬에서는 항상 'frame-'
scrollBudget: 4200, // 전체 통과를 위한 누적 입력 픽셀
// 선택 사항: padWidth (기본값 3), ext (기본값 'jpg')
})
클래스는 자동으로 body.scrub-page를 첨부하여(CSS를 통해 스크롤을 잠금), 모든 프레임을 미리 로드하고, 스크롤 파생 대상 프레임을 향해 RAF 기반 lerp(0.22 계수)를 실행하며, data-start/data-end 범위에 현재 진행률이 포함된 장면을 교차 페이드합니다.
강제 제약 조건 (양보할 수 없는 사항)
다음은 참조에 포함되어 있으며 위반 시 경험을 망가뜨립니다:
- 5개 장면, 고정 진행률 창:
0.00–0.20,0.22–0.40,0.42–0.60,0.62–0.80,0.82–1.00. 장면 간 0.02 간격은 의도적입니다 — 비트 사이에 "이미지만, 텍스트 없음"의 순간입니다. 히어로(장면 1)와 최종(장면 5)은 각각data-fade="0.30"과data-fade="0.18"을 사용하여 가장자리에서 더 오래 유지됩니다. 중간 장면은 기본값 0.25를 사용합니다. - 스크럽 아래에
.end섹션 없음. 최종 장면에 CTA가 포함됩니다. 전체 페이지는 하나의 잠긴 뷰포트입니다. - Anton + Caveat + Inter — 대담한 모든 것에는 대문자 Anton, 손글씨 악센트(골드/앰버/크림)에는 Caveat, 본문 리드 텍스트에는 Inter. 절대 대체하지 말고, 네 번째 글꼴을 추가하지 마십시오.
- 오프-화이트
#f5f1ea, 절대#fff아님 — 이미 CSS에var(--text)로 있습니다. - **프레임 이름은
frame-NNN.jpg**이며 총 개수 너비로 제로 패딩됩니다(클립이 1000 프레임 미만이므로 3자리가 표준입니다. JS는 총 개수에서 카운터 너비를 자동 계산합니다). - slug는 폴더 이름이자 HTML 파일 이름의 기본 이름입니다 —
hope/,hope.html. 예외 없음. 통합 단계에서는 이를 가정합니다.
막혔을 때 볼 곳
- 이 저장소에 번들된 참조 쇼케이스:
examples/parasites/— github.html, lion.html, hope.html, style.css, parallax.js, index.html. 출력이 가시적으로 이들과 다르다면, 잘못된 것입니다. 다시 읽으십시오. references/copy-guide.md— 5개 장면을 실제로 시네마틱하게 느껴지도록 작성하는 방법.references/showcase-integration.md— 기존 허브에 추가할 때 필요한 정확한 수정 사항.assets/landing-page-template.html— 플레이스홀더가 있는 표준 구조.assets/hub-template.html— 완전히 새로운 쇼케이스를 생성할 때만 사용됩니다 (처음부터 3개의 카드).
두 가지 실제 예시 호출
독립형: 사용자에게 desk.mp4라는 단일 클립이 있고 랜딩 페이지를 원합니다.
- slug + 테마를 묻습니다.
desk.mp4에서 추출기 실행 →./desk/frame-NNN.jpg. style.css+parallax.js를 프로젝트 루트에 복사합니다.- 템플릿에서
desk.html을 작성합니다. 내비게이션에는 자신에 대한 링크 하나만 있습니다. - 완료.
python -m http.server로 서비스하라고 사용자에게 알립니다.
쇼케이스 추가: 사용자가 기존 parasites 폴더에 hope.mp4를 추가합니다.
- Slug =
hope. 추출 →hope/frame-NNN.jpg. (기존style.css+parallax.js재사용.) - 템플릿에서
hope.html작성. - 쇼케이스 통합 실행:
index.html에 세 번째 카드 추가,github.html과lion.html의 내비게이션 바에Hope링크 추가, 이전 랜딩의 최종 장면을Next: Hope →CTA로 연결. - 새로운 악센트 색상을 도입하는 경우
:root에 추가하고style.css에.script.X+.cta.X규칙을 추가합니다.