When to use
- When creating card news for Instagram feed/carousel
- When you need mobile still images + a swipe simulation mp4, not a video (1920×1080)
- When condensing only the key messages into 10 or fewer cards
Child template skill structure
This skill handles the overall card news assembly, topic generation, overview, and render flow. The detailed implementation of individual card types is the source of truth in the 4 child skills below.
| Template | Child skill | Role |
|---|---|---|
photo-cover |
hyperframes-card-news-work-photo-cover |
Full-bleed photo + brand/source black box + large bottom headline |
video-cover |
hyperframes-card-news-work-video-cover |
Video directly under stage + overlay card + large bottom headline |
stat |
hyperframes-card-news-work-stat |
One big number + label + short description |
image-feature |
hyperframes-card-news-work-image-feature |
Image frame + blur/gradient background + headline + body |
When writing or modifying cards, apply the corresponding child skill as well. Do not create card types other than these 4 or data-skill values.
When newly creating or replacing the cover/representative image for AI news, apply the auxiliary skill hyperframes-card-news-fomo-image-directionas well. This auxiliary skill translates facts into visual metaphors and image prompts, but does not define new card types.
It is a completely different format from the existing hyperframes-slide-work-* skill (1920×1080, 16:9). Because card news is read in mobile feeds:
- Fonts are large (body ≥ 40px)
- Less information per card (one card = one message)
- Visual elements are strongly attached (photos, blur backgrounds, large typography)
Canvas variant
| variant | Resolution | Ratio | Usage |
|---|---|---|---|
| portrait (default) | 1080×1350 | 4:5 | Displayed largest in the Instagram feed. Most card news. |
| square | 1080×1080 | 1:1 | Consistent size anywhere in classic Instagram and profiles. |
Variant selection is determined by choosing a starter template at topic generation time. There is no runtime switch.
template-portrait.html— 4:5 default templatetemplate-square.html— 1:1 template
Topic generation flow
# 1. 원하는 variant의 스타터를 복사
cp -r topics/_template topics/<주제-이름>
cp .codex/skills/hyperframes-card-news/template-portrait.html topics/<주제-이름>/index.html
# 또는 square:
# cp .codex/skills/hyperframes-card-news/template-square.html topics/<주제-이름>/index.html
# 2. meta.json 수정 (id / name을 <주제-이름>으로)
# 3. AI 뉴스 표지라면 fomo-image-direction으로 A/B/C 이미지 콘셉트를 먼저 기획
# 공식 자산 우선, 생성 이미지의 글자·로고·UI 오류를 제거하고 한 시안을 선택
# 4. 4개 템플릿(photo-cover / video-cover / stat / image-feature)을 조합해 카드 구성
# 각 카드 구현은 hyperframes-card-news-work-* 하위 스킬을 따른다.
# 5. 검증
npx hyperframes lint topics/<주제-이름>
Existing topics/_template/ 의 index.html is based on 1920×1080. When creating card news, it must be overwritten.
Common rules
- Root data dimension:
<div id="root" data-width="1080" data-height="1080">(square) ordata-height="1350"(portrait) html, body, .cardSet the CSS dimension according to the variant (1920×1080 forbidden)- Each card requires
class="clip"+data-start/data-duration/data-track-indexfield - Default duration per card is 5 seconds (reduced from 6 seconds for 16:9 video — card news has a shorter reading rhythm)
- Timeline registration:
window.__timelines["main"] = gsap.timeline({ paused: true })required word-break: keep-allFor all text elements — Korean natural line breaking- Outer padding 100–120px (based on 1080 canvas)
4 templates
All examples are based on 4:5 portrait (1080×1350). For square, use the same values but change only the vertical value to 1080.
| Template | Use | Features |
|---|---|---|
| photo-cover | Cover (photo type) | Full-bleed photo + overlay headline. News/magazine-style hooking. |
| video-cover | Cover (short video type) | Full-bleed short silent video + bottom black gradient + bold headline. On-site feel hooking. |
| stat | Number emphasis | One large number + label. |
| image-feature | Photo + body text | Blurred background + centered image + title + 3–5 lines of body text. |
All 4 are video·image·large typography·color block -centered. Traditional "question card" or "title+bullet" slide styles look weak in the card news feed, so they are excluded. For detailed implementation, prioritize the
hyperframes-card-news-work-photo-cover,hyperframes-card-news-work-video-cover,hyperframes-card-news-work-stat,hyperframes-card-news-work-image-featureskill.
Template selection rules
- Opening:
video-coverorphoto-cover - Number·year·ratio-centered:
stat - Image·context explanation-centered:
image-feature - Closing:
photo-coverorimage-feature - Do not create question-type cards, generic title+bullet cards, or arbitrary
timeline/quote/closingtypes.
1. photo-cover — full-bleed photo hooking
The opening pattern most frequently used by Korean card news. On top of a full-bleed photo + bottom scrim gradient, a bold 2-line headline, optionally a circular inset at the top right, and at mid-height a @핸들 overlay.
<div id="c-1" class="card clip photo-cover"
data-start="0" data-duration="5" data-track-index="0">
<div class="bg-image">
<img src="assets/hook.jpg" alt="..." />
</div>
<!-- 인셋은 선택 — 보조 인물·참고 이미지가 필요할 때만 -->
<div class="inset-avatar">
<img src="assets/inset.jpg" alt="..." />
</div>
<div class="hook-handle">@handle_name</div>
<div class="hook-title">
<span class="line">헤드라인 첫째 줄</span>
<span class="line">헤드라인 둘째 줄</span>
</div>
<div class="page-indicator">01 · 04</div>
</div>
CSS essentials
.card.photo-cover—padding: 0(full-bleed),overflow: hidden.bg-image—position: absolute; inset: 0; z-index: 0,img { width: 100%; height: 100%; object-fit: cover }.inset-avatar—position: absolute; top: 80px; right: 80px; width: 220px; height: 220px; border-radius: 50%; overflow: hidden; border: 4px solid rgba(255,255,255,0.7).hook-handle— brand/source identity area. Always place it on a black box:display: inline-flex; width: max-content; max-width: 760px; padding: 12px 18px; border-radius: 8px; background: rgba(0,0,0,0.82); box-shadow: 0 6px 18px rgba(0,0,0,0.35); color: #fff.hook-title—position: absolute; left: 0; right: 0; bottom: 0; padding: 260px 80px 140px; background: linear-gradient(to top, rgba(0,0,0,0.96) 0%, rgba(0,0,0,0.82) 34%, rgba(0,0,0,0.48) 64%, transparent 100%).hook-title .line—display: block; font-size: 64–72px; font-weight: 800; color: #fff; line-height: 1.28- The bottom 35% where the copy sits should be treated as nearly black. Prioritize text legibility over the photo's original brightness.
GSAP
tl.from("#c-1 .bg-image img", { scale: 1.08, duration: 1.2, ease: "power2.out" }, s + 0.0);
tl.from("#c-1 .inset-avatar", { scale: 0, opacity: 0, duration: 0.7, ease: "back.out(1.7)" }, s + 0.4);
tl.from("#c-1 .hook-handle", { y: 20, opacity: 0, duration: 0.6, ease: "power2.out" }, s + 0.8);
tl.from("#c-1 .hook-title .line", { y: 40, opacity: 0, duration: 0.7, ease: "expo.out", stagger: 0.12 }, s + 1.1);
tl.from("#c-1 .page-indicator", { opacity: 0, duration: 0.5, ease: "power2.out" }, s + 2.0);
Photo sourcing: Prioritize official product images, screenshots, and real photos with clear usage permission. For AI news covers, first decide on one protagonist, one article-specific object, and one visual metaphor with hyperframes-card-news-fomo-image-direction. Do not use generic AI workspaces, robots, or holograms that could be attached to any article. Final assets must always be saved locally to assets/and referenced by relative path.
2. video-cover — full-bleed short video hooking
An opening pattern that lays a moving scene of a real place, site, product, or interface at the start of the card, like the reference the user provided. It has the same goal as photo-cover, but the background is not an image but a short silent video. At the bottom, lay a strong black gradient and place a large white 2-line headline on top.
<video id="c-2-video" class="cover-video-media clip"
src="assets/hook.mp4" poster="assets/hook-poster.jpg"
data-start="5" data-duration="5" data-track-index="0"
muted autoplay loop playsinline preload="auto"></video>
<div id="c-2" class="card clip video-cover"
data-start="5" data-duration="5" data-track-index="1">
<div class="video-shade" aria-hidden="true"></div>
<div class="hook-kicker">REAL FOOTAGE</div>
<div class="hook-title">
<span class="line">만화 아니고</span>
<span class="line">실제 건널목 입니다</span>
</div>
<div class="page-indicator">02 · 04</div>
</div>
CSS essentials
.cover-video-media—<video>는 Do not put it inside the card; place it directly under the stage.position: absolute; top: 0; left: 0; width/height: canvas; object-fit: cover; z-index: 0.card.video-cover—padding: 0,background: transparent,overflow: hidden,z-index: 1. Serves as the text/gradient overlay placed on top of the video.<video>— must be uniqueid,class="clip",data-start,data-duration,data-track-index,muted autoplay loop playsinline preload="auto"Specify. Use the same start/duration as the parent card.- The track is kept separate. For video use
data-track-index="0", and for the overlay card body usedata-track-index="1"to avoid the same track overlap error. .video-shade— a double gradient that makes the top lightly dark and the bottom strongly dark. The bottom 35% where the copy sits is treated as nearly black..hook-kicker— Optional.REAL FOOTAGE,LIVE SCENE,ON LOCATIONA field-reporter-style label like this. Remove if not needed..hook-title—position: absolute; left: 0; right: 0; bottom: 0; padding: 0 80px 150px.hook-title .line— 64–72px, weight 800–900, white, line-height around 1.2, shadow required.page-indicator— white around 70%
GSAP
tl.from("#c-2-video", { scale: 1.08, duration: 1.4, ease: "power2.out" }, s + 0.0);
tl.from("#c-2 .hook-kicker", { y: 18, opacity: 0, duration: 0.55, ease: "power2.out" }, s + 0.7);
tl.from("#c-2 .hook-title .line", { y: 42, opacity: 0, duration: 0.75, ease: "expo.out", stagger: 0.12 }, s + 1.0);
tl.from("#c-2 .page-indicator", { opacity: 0, duration: 0.5, ease: "power2.out" }, s + 2.0);
Usage tips
- Use on the first or second card. Especially strong for twist-type hooks like "Is this real?"
- A 3–6 second loop is best for video, and no audio is used. If needed, follow a separate
<audio>rule. posterAlways include an image so the overview, initial loading, and paused frames don't look empty.- Set the shooting/cropping baseline so important subjects in the video aren't hidden by the bottom text.
- If the direction the copy sits on isn't the bottom, change the gradient axis to match that direction. E.g., for right-side copy use
to left, for left-side copy useto right. - Suitable for dark night scenes, city streets, product usage scenes, screen recordings, and field clips.
3. stat — one big number
Number-impact card. Metrics: 1 per card (on Instagram, don't list multiple numbers).
<div id="c-3" class="card clip stat-card"
data-start="10" data-duration="5" data-track-index="0">
<div class="eyebrow">By the Numbers</div>
<div class="stat-num">1,000<span class="stat-unit">+</span></div>
<div class="stat-label">전 세계 매장 수</div>
<div class="stat-desc">30여 개국에서 운영 중 (2024 기준)</div>
<div class="page-indicator">03 · 04</div>
</div>
CSS essentials
.card.stat-card—justify-content: center; align-items: center; text-align: center.stat-num— 240–280px, weight 800, line-height 1, negative letter-spacing,font-variant-numeric: tabular-nums.stat-unit— 64–72px, weight 500, accent 색.stat-label— 40–44px, weight 600, margin-top 32–40px.stat-desc— 28–32px, weight 400, dim, line-height 1.45
GSAP
tl.from("#c-3 .eyebrow", { y: -15, opacity: 0, duration: 0.5, ease: "power3.out" }, s + 0.2);
tl.from("#c-3 .stat-num", { scale: 0.85, opacity: 0, duration: 0.9, ease: "back.out(1.6)" }, s + 0.5);
tl.from("#c-3 .stat-label", { y: 20, opacity: 0, duration: 0.6, ease: "power2.out" }, s + 1.3);
tl.from("#c-3 .stat-desc", { opacity: 0, duration: 0.6, ease: "power2.out" }, s + 1.6);
4. image-feature — blurred background + centered image + body text
A story-type template used when explaining an image at length. Lay the same image large and blurred/darkened underneath, place the original image cleanly on top, then arrange a headline + 3–5 lines of body text below.
<div id="c-4" class="card clip image-feature"
data-start="15" data-duration="5" data-track-index="0">
<div class="feature-bg" aria-hidden="true"
style="background-image: url('assets/featured.jpg');"></div>
<div class="feature-content">
<div class="feature-frame">
<img src="assets/featured.jpg" alt="설명" />
</div>
<div class="feature-headline">이미지가 전하는 메시지 한 줄</div>
<div class="feature-body">
<p>본문 첫 번째 단락 — 배경, 맥락, 사건을 간결히.</p>
<p>본문 두 번째 단락 — 부연 설명 또는 결과를 한두 문장.</p>
</div>
</div>
<div class="page-indicator">04 · 04</div>
</div>
Load the blurred background with CSS
background-image.<img>If you nest the tag twice, the linter will issue aduplicate_media_discovery_riskwarning.
CSS essentials
.card.image-feature— dark bg (#0b0d10등),padding: 0,overflow: hidden.feature-bg—position: absolute; inset: -40px; z-index: 0; background-size: cover; background-position: center; filter: blur(48px) brightness(0.45); transform: scale(1.12)— heavily blur the same image as a CSS bg.feature-content—position: relative; z-index: 1; padding: 96px 80px; display: flex; flex-direction: column; align-items: center; height: 100%.feature-frame—width: 78%; aspect-ratio: 1/1; border-radius: 12px; overflow: hidden; box-shadow: 0 12px 32px rgba(0,0,0,0.45).feature-headline— 56–64px, weight 700, color#fff, line-height 1.25, margin-top 56px.feature-body p— 28–32px, weight 400, line-height 1.55, colorrgba(255,255,255,0.82).feature-body p + p—margin-top: 16px
GSAP
tl.from("#c-4 .feature-bg", { scale: 1.22, duration: 1.2, ease: "power2.out" }, s + 0.0);
tl.from("#c-4 .feature-frame", { scale: 0.9, opacity: 0, duration: 0.9, ease: "power3.out" }, s + 0.3);
tl.from("#c-4 .feature-headline", { y: 24, opacity: 0, duration: 0.7, ease: "expo.out" }, s + 1.0);
tl.from("#c-4 .feature-body p", { y: 16, opacity: 0, duration: 0.6, ease: "power2.out", stagger: 0.12 }, s + 1.4);
tl.from("#c-4 .page-indicator", { opacity: 0, duration: 0.5, ease: "power2.out" }, s + 2.1);
Usage tips
- When the image is the center of the story (showing and explaining a person, place, or object)
- Body text within 2–3 paragraphs, each paragraph 1–2 sentences
- Using the same image for both background and frame is the default design (it extends the color and mood)
Generating the overview
overview-template.html Copy and fill in the card content. It's already --canvas-w, --canvas-h, --card-aspect parameterized with CSS variables.
Required references: overview.html 은 You must
hyperframes-overview-editinclude the Edit feature of the skill. Whether creating new or modifying an existing file, reference that skill and check that the Edit button + CSS + JS (card news uses thejs-card.htmlvariant) are not missing. Verification command:grep -L "class=\"edit-btn\"" topics/*/overview.html.
Required rules for thumbnails and export
The left strip thumbnail must be maintained. However, the thumbnail must not be a separate design but a preview that is a scaled-down version of the right detail card DOM.
- The thumbnail is
card.cloneNode(true)and specify.thumb .card { display: flex; transform: scale(...); }. It must use the same display model as the right.detail-frame .card.active { display: flex; }so that the scaled thumbnail and the editing screen layout match. - Thumbnail label (
.thumb-label) is hidden by default so it does not cover the card content, and shown only on hover. - After Edit → Done, for the changed card number,
syncThumbFromCard(n)to re-clone the latest right DOM and immediately update the left thumbnail. - PDF/print/export must be based not on the left strip but on the original card inside the right
#detail-frame.@media printin.strip,.main-header, hide the Aim/Edit UI, and.detail-frame .cardoutput the entire thing in page units by card size. - This rule applies not only to the sample but to all newly generated card news overview.html files.
1. Copy template
cp .codex/skills/hyperframes-card-news/overview-template.html topics/<주제>/overview.html
2. Replace :root variables
- portrait:
--canvas-w: 1080,--canvas-h: 1350,--card-aspect: 4 / 5 - square:
--canvas-w: 1080,--canvas-h: 1080,--card-aspect: 1 / 1
3. Convert cards to overview structure
index.html 의 각 <div id="c-N" class="card clip ..." data-start="..."> to overview format:
clipRemove classdata-start/data-duration/data-track-indexRemoveid="c-N"Removedata-card="N"+data-skill="<photo-cover|video-cover|stat|image-feature>"Add
Card news is not a video slide, so .brand / .slide-num do not include footer elements such as. The card itself's .page-indicator already serves as the number.
<div class="card photo-cover" data-card="1" data-skill="photo-cover">
<div class="bg-image"><img src="..." /></div>
...
<div class="page-indicator">01 · 04</div>
</div>
4. Serving
If there is a card containing an image, must be an HTTP server로:
bash .codex/skills/hyperframes-overview/serve.sh topics/<주제> 8766
# → http://localhost:8766/overview.html
Video render
npx hyperframes render topics/<주제> as is. The renderer reads the root data-width / data-height as is and:
- portrait variant → 1080×1350 mp4
- square variant → 1080×1080 mp4
4 cards, 5 seconds each → 20-second mp4. The render result is in the root renders/ or topic folder renders/ .
9:16 for Instagram Reels?
The current skill does not support it. Since card news and Reels have different production flows, it is recommended to separate them into a separate skill.
Writing principles
- One card = one message. If two or more messages are included, split the card.
- Visual elements required — In all 4 templates, an image or large typography is the star of the card. A plain list of text paragraphs does not fit well.
- The first card is photo-cover or video-cover. To stop scrolling in the feed, a strong still image or actual motion is needed.
- 3–7 cards recommended. Too few makes the pacing short, too many increases drop-off.
- The last card is a CTA or summary —
image-feature,photo-cover, closing with a logo/follow-type block. - Color palette is freebut high contrast is required. If the feed thumbnail looks blurry, it is a failure.
Markdown detection rules (when linked with the generator)
# [photo-cover] @handle_name

 # 선택
헤드라인 첫째 줄
헤드라인 둘째 줄
# [video-cover] REAL FOOTAGE

video: assets/hook.mp4
만화 아니고
실제 건널목 입니다
# [stat] By the Numbers
$ 1,000+
전 세계 매장 수
설명 한 줄
# [image-feature] 헤드라인

본문 첫 번째 단락.
본문 두 번째 단락.
The text inside the brackets is the template type: photo-cover / video-cover / stat / image-feature.
Instagram upload body caption
After card news rendering is finished, when actually uploading to Instagram post body (caption) is also needed. The hook, lead, key bullets, viral stats, and 20 hashtags structure instagram-caption-ko.txt generation is handled by a separate skill hyperframes-instagram-caption This handles it. Automatically written based on the card content.
Checklist
Before generation:
- Decide variant (portrait / square)
- Decide total number of cards (3–7 recommended)
- Pre-map each card's template type (first card = photo-cover or video-cover)
- If it is AI news, cross-check the key facts and dates with more than 2 sources
-
hyperframes-card-news-fomo-image-directionDecide the fact/person/metaphor A/B/C cover direction with
During creation:
- On every card
class="card clip"+ timing attribute -
#root에data-composition-id="main"+ matching the variantdata-width/data-height -
window.__timelines["main"]register a paused timeline on - Place images
assets/as relative paths in - video-cover videos should be placed in
assets/as mp4/webm, anddata-start/data-duration+muted autoplay loop playsinline posterspecify - image-feature background should use CSS
background-image(avoid duplicate media warnings) - For Korean text
word-break: keep-all
After completion:
-
npx hyperframes lint topics/<주제>→ 0 errors - Generate overview.html + check in the browser via HTTP server
- Check whether the cover protagonist and event are readable within 1 second in the overview's thumbnail scaled to around 320px
- Mark cards or captions so AI-generated/staged images are not mistaken for real on-site photos
-
npx hyperframes renderGenerate mp4 with, and actually open it on mobile