Skill instructions
lyra-ad-concept-multiplier65.6 KB
View saved version →
---
name: lyra-ad-concept-multiplier
description: "Ad concept multiplier for mobile app video ads in Lyra. Takes a concept (a winning ad, a Lyra workflow, a finished video, or a concept name like \"Authority figure\") and makes new ads on it with new angles, in one of two ways the user picks - A. Perspectives (the team framework, concept → angles → hooks: who else tells it and how they argue it, e.g. doctor, teacher, trainer, mom) or B. Reasons (the proven wrapper kept, a new reason to care: another pain, desire, objection, moment or feature from the Brand Kit, in the situation where it happens). Each angle is built as a Lyra variation. Use for \"more ads like this winner\", \"same concept, new angles\", \"multiply this concept\", \"1 concept, 4 angles, 20 hooks\", \"same format, different pain / story / setting\", \"the angle is tired, keep the format\", \"iterate on the winner\". Not for new openings only (lyra-video-hooks) or the same script for another person or market (lyra-audience-variations). Core video rules come from lyra-video-ad-generation."
---
# lyra-ad-concept-multiplier
Mini skill. Takes a concept that works (or one the team wants to explore) and makes **new ads on it with new angles**. There are two ways to do it, and they mean different things by "angle", so the user picks one (or both, as two separate rounds):
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
- **A. Perspectives** (the team framework: concept → angles → hooks). The concept is a creative mechanism in 3 to 4 words ("Authority figure"). Each angle is a new perspective inside it, often a new voice with its own argument (the doctor, the teacher, the trainer, the mom), and each angle gets its own hooks. One concept → 3 to 4 angles → about 5 hooks each.
- **B. Reasons** (the proven wrapper). A winning ad keeps everything that made it work (format, beats, timing, hook mechanism, camera, person, look, music, CTA), and only the reason to care changes: another pain, desire, objection, moment or feature from the Brand Kit, in the situation where it happens. One winner → 3 new angles + the original as control.
One new angle = one Lyra **variation** of the original workflow.
**Why it works.** A concept is the expensive thing to find; angles are where the next wins usually are. Mode A expands a concept into the space around it and finds which perspective carries it best. Mode B keeps a proven wrapper and finds which reason to care sells inside it, as a clean test of one thing. Both give ads that are new to the viewer and to the platform (new words, new people or places, a new story), which Meta's delivery needs: it groups near-identical creatives as one (check the current behaviour).
**This is a way of thinking, not a script.** The rules below are defaults and good practice. Use judgment: when a different angle, situation or build serves the concept better, do it and say why in one line. Only a few things are fixed: truth (no invented claims, reviews, numbers or credentials; an AI person is never a real customer or a real expert), the Brand Kit's facts (every angle is a real pain or desire answered by a real feature), the locked part of the mode the user picked, the product and its real UI, Lyra's technical limits, and the user's explicit choices.
**Method.** The team framework (concept → angle → hook, each level tested separately), GBP (Gut, Brain, Pocket) and More, Better, New. `lyra-video-hooks` is MORE on the Gut (new openings, same body). `lyra-audience-variations` keeps the Brain and changes the world it is shown in. This skill is **MORE on the Brain**: new angles on a concept. The Pocket (CTA, offer, end card) stays.
**Base skill first.** Everything not written here follows `lyra-video-ad-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, prompt rules, models (Reference A), brief and scenes (B), audio (C), app UI (D), consistency (E), prompt craft (F), errors (G), de-slop (H), Brand Kit (I), Meta app ads (J). This file only adds what is specific to multiplying a concept. If the two disagree, the user wins, then this file, then the base skill.
**Other skills for their parts.**
- Person, place, voice, speech, camera setups, formats, realism, casting → `lyra-ugc-video`.
- Hooks: the ~5 hooks per angle in mode A, the hook line of every angle in mode B (same mechanism, new words), new openings on a winning angle → `lyra-video-hooks`.
- A new feature screen, a UI moment or the end card → `lyra-ui-motion-video` (only the user's screenshots, checked word by word).
- The same script for another person, segment or market → `lyra-audience-variations`.
- A competitor's ad as the source → `lyra-copy-competitor-ad` first; the multiplier works on our own version once it exists.
---
## The words: concept, angle, hook
The team uses the three levels from the framework ("a zoom-in effect"):
| Level | What it is | Size | Example (fitness app) |
|---|---|---|---|
| **Concept** | the basic creative mechanism, the big idea or format | 3 to 4 words | Authority figure · Before/After · Social proof · Challenge · Myth-busting · POV · Warning · Negative emotion |
| **Angle** | a specific perspective inside the concept: who says it, from which lens, with which persuasive point | 6 to 7 words | "A trainer tells clients about protein timing" |
| **Hook** | the execution that earns attention in the first seconds | 1 sentence | "Stop doing crunches." |
Other sources order these words differently (some put the angle, as the argument, above the concept). In Lyra skills the team order is used: concept → angle → hook. Two more terms:
- **The built concept** is one specific ad made on a concept (code `C1` in names); it may have been built with any of our skills.
- **The wrapper** of a built ad is everything about how it is told: format, beat structure and timing, hook mechanism, camera, person, look, audio role, CTA. Mode B keeps it; mode A keeps only the concept mechanism and the Pocket.
**The same words inside Lyra.** Lyra's own nodes use these words a little differently; know which one you are reading:
| Where | "Angle" or "concept" there means | How this skill reads it |
|---|---|---|
| The team framework (this skill, mode A) | angle = a perspective inside a concept, 6 to 7 words | as is |
| This skill, mode B | angle = a reason to care: a pain, desire, objection, moment or feature | as is |
| Lyra's **Ad Brief** node, field "Concept angle" | the whole creative idea being tested, up to 100 characters ("UGC before/after with dermatologist endorsement and urgency offer") | the brief line of one angle: concept + angle + proof + offer in one phrase |
| Lyra's **Ad Brief**, field "Hook mechanism" | question, statistic, before after, social proof, curiosity gap, direct benefit, pain point, FOMO, shock value, trend riding, relatability, authority claim | the same words can be concepts in the team framework (Before/After, Social proof, Authority figure); a hook mechanism is only the opening |
| Lyra's **Creative Hypotheses** node | `new_angle` = a new argument for the same people · `new_persona` = new people with their own problem · `new_concept` = a new format and story · `improve` = one weak element of a winner; tags in the `angle` namespace shape the whole ad, not one funnel stage | see the borders below; its own MODE A / MODE B (whole account / one video) has nothing to do with this skill's modes |
| Lyra's **Ad Variation** node | single-variable mode (one dimension changes, every other one listed as held constant) or multi-variable mode | mode B is single-variable (the angle); mode A is multi-variable |
**The speaker is not the persona.** Lyra keeps two things apart: the **persona** is who the ad is for (their situation and goal), the **presenter** is who is on screen. In mode A the presenter changes with the angle (the doctor, the teacher); the persona stays the account's people unless the angle is meant for new people. People are the same when they share the situation and the goal the ad speaks to, not when they look alike: a male beginner runner and a woman training for a half-marathon are different people, although both run.
---
## Two ways to multiply: pick with the user
| | **A. Perspectives** (team framework) | **B. Reasons** (proven wrapper) |
|---|---|---|
| The question | Who else could tell this, and how would they argue it? | What else can this same ad say? |
| An angle is | a perspective inside the concept: a speaker, a role, a lens, each with its own point | a reason to care for a segment: another pain, desire, objection, moment or feature (a "motivation layer": a fear, a frustration, a desire) |
| Stays | the concept mechanism, the brand, the Pocket (CTA, offer, end card); the format family if the user wants | the whole wrapper: format, beat jobs and timing, hook mechanism, camera, cut rhythm, the person, look, audio role, music, the Pocket |
| Changes | the person or role, the place, the script, the argument, the hooks (about 5 per angle) | the reason, the situation where it happens, the script, the hook line (same mechanism) |
| Source | a concept name, a brief or a built ad | a built ad: a winner (a Lyra workflow or a finished video) |
| Scale | 1 concept → 3 to 4 angles → about 5 hooks each (up to 20 videos) | 3 angles + the original as control, one ad each |
| The test reads | which perspective makes this concept work, then which hook | which reason to care sells in this wrapper |
| Best when | exploring a concept's territory; early in a campaign; the user thinks in the framework's tree; a concept that lives on its speaker (Authority figure, Social proof, POV) | a validated winner; its angle fatigues but the format still holds; clean tests one variable at a time |
| Watch out | several things change at once, so a winner says "this perspective works", not "this word works" | narrow: the wrapper itself is never tested |
Both modes can run on one concept, as two separately named rounds (`A`-round and `B`-round), so the media buyer can compare the methods too.
### How to ask the user (plain words, exaggerated on purpose)
Ask once, early (Step 1), in the user's language, built on their app and their concept, with a recommendation. The examples are deliberately simple so the difference is obvious. Template (fictional fitness app, the winner is a doctor warning about sitting too long):
> There are two ways to make more ads from this concept. Which do you want?
> **A. Other people, other arguments** (concept → angles → hooks). The idea "an authority tells you to move" stays, but other people say it, each in their own way: a doctor ("Prescription: 10 minutes a day"), a teacher ("Homework: 10 squats"), a trainer ("Stop doing crunches"), a mom ("Have you moved today?"). About 5 hooks for each. Good for finding which voice works best.
> **B. Same ad, new reason** (proven wrapper). The same doctor, the same format, the same rhythm and ending, but each new ad is about a different problem: back pain at the desk, bad sleep, "no time for the gym". Good for a clean test of which problem sells.
> I'd recommend B, because your doctor ad already wins and B keeps everything that made it win. We can also do both, as two separate rounds.
Recommend by the source: a validated winner whose format holds → B · a concept name or an early concept, or a concept that lives on its speaker → A · the user already thinks in "1 concept, 4 angles, 20 hooks" → A.
### Borders with the other skills
- Only the first 3 s change → `lyra-video-hooks`.
- **The same script** said by another person or in another world (a nurse saying the same lines, the bedroom in São Paulo), words change only where tied to the person or place → `lyra-audience-variations`.
- **Another person with their own argument** (the teacher with "homework: 10 squats" instead of the doctor's prescription) → this skill, mode A.
- **A new reason to care** or a new situation where another pain happens (bed at 2 am → desk in exam week), the same wrapper → this skill, mode B.
- **Another concept** (Authority figure → Challenge) → a new concept (base skill).
- **A hypothesis card from Lyra's Creative Hypotheses** (`what_to_do`, `why`, `what_to_change`): `improve` is one element on a winner's weak step → `lyra-video-hooks` when the weak step is the opening, otherwise a one-element edit of that workflow (a variation, everything else held constant) · `new_angle`, `new_persona`, `new_concept` are new videos invented from a moment, not assembled from the account's videos → build each with the base or format skill exactly as the card says, then multiply it here once it wins. A card whose idea is "the same wrapper, a new reason" is mode B; one that is "another speaker with their own argument" is mode A.
**The ladder of iterations:** hooks (the first 3 s) → audience variations (who and where, same words) → concept multiplier (new angles) → a new concept.
**Every angle is a hypothesis**, written as one line: "We think [segment] installs more when [concept] is told [through this perspective / about this reason], because [evidence from the Brand Kit or research]."
**Different enough to count.** Angles must differ in the perspective or the reason, not in wording: "can't fall asleep" and "lying awake at night" are one angle; "a trainer" and "a gym coach" are one angle. Each new ad must read as a different ad in the first 3 s (a new person or place, a new hook line) and in the transcript.
---
## Mode A: Perspectives (concept → angles → hooks)
### The concept card
One note, "Concept card": the concept name (3 to 4 words) · its mechanism in one line (what makes it persuade: "an authority gives a simple order the viewer can follow today") · why it works for this app (from the original ad's numbers or the research) · what stays across all angles (the Pocket, the brand look, the format family if the user wants one, the length).
If the source is a built ad, also note what the original angle is: it is angle 1 of the tree, the control.
### Angles: perspectives inside the concept
An angle in mode A answers "who tells it, from which lens, with which point?". It is written in 6 to 7 words and expands the space around the concept. Where perspectives come from:
| Concept | Ways to find perspectives | Example angles (fitness and nutrition apps) |
|---|---|---|
| Authority figure | different roles the audience listens to | doctor · teacher · trainer · mom · a coach: "why tracking alone doesn't change habits" |
| Before / After | different "befores" | my day of eating before vs after · my questions before: 10 browser tabs, after: one answer · my hit-rate before vs after a week of reminders |
| Social proof | different sources of proof | "my gym friends keep asking what app I use" · replying to a real comment · first-week wins (only real ones) |
| Challenge | different challenges and their stakes | a 7-day protein challenge · "I asked the app every food question for a week" · making it past day 14 |
| Myth-busting | which belief is broken | "skipping meals isn't discipline" · "counting calories isn't the hard part" |
| POV | which moment the viewer lives | POV: your coach texts you right before you get hungry · POV: you finally know what to order |
| Warning | which mistake | "stop guessing your protein" · "don't download another calorie app until you see this" |
| Negative emotion | which feeling | fed up of tracking and still not knowing what to eat · crying because the language is hard |
Every angle is tied to **a segment** from the Brand Kit and to **evidence** (the Brand Kit, reviews, the research agent, past results). No evidence → the angle is marked **Explore**; evidence → **Adapt**. A good tree mixes both (mostly Adapt, one or two Explore).
**The person is part of the angle.** In mode A the speaker often *is* the perspective, so the person changes with the angle: a new character card per angle (`lyra-ugc-video`, casting from the audience). Keep the place, light and look consistent only where the concept needs it.
**The audience check, per angle** (Lyra's Hypothesis Audience Check). A new speaker must not quietly change who the ad is for. For every angle write: who the angle is for · who the original was for · same people: **yes** (the same situation and goal, even if the person on screen looks different) / **no** (another stage, goal, need or identity: the speaker brings their own situation with them) / **unclear** (say what is missing) · one plain sentence why. "No" is fine only when the angle is meant for new people: then name it as a new-persona angle with its own problem, in its own segment row. A mom telling *other moms* to move is still the fitness app's audience only if the account speaks to moms.
**Professionals and authority.** An AI person is never presented as a real expert. No white coat with "as a doctor I recommend", no titles, no medical, financial or legal advice. Authority angles work as: a clearly playful role in a skit ("Prescription: 10 minutes of walking", the teacher's "homework"), an **insider** without claimed credentials (`lyra-ugc-video` archetypes), a parent or a friend, or a **real** expert the brand works with (their consent, their words). Health claims only from the Brand Kit.
### Hooks per angle
Approve the angles first; write hooks only after ("do not ask for detailed hooks right away"). Then about **5 hooks per angle** by `lyra-video-hooks` (pain map, kinds, writing rules), each a different idea, all in that angle's voice. Within one angle the hooks share one body (hooks skill, mode A: same body, music and CTA), so the hook test inside an angle stays clean.
The tree is shown to the user before anything is built:
> **Concept** C01 Authority figure (1 idea)
> **Angles** A1 doctor · A2 teacher · A3 trainer · A4 mom (4 perspectives)
> **Hooks** A1: posture warning · X-ray reveal · bed-rotting diagnosis · prescription: 10 minutes · heart rate check / A2: blackboard drawing · you now vs in a month · homework: 10 squats · failing grade · calorie math / … (20 videos)
**Budget.** 20 finished videos is a lot of credits. Default first round: **2 to 3 angles × 3 hooks**, angle bodies on images first; more hooks for the angles that show promise.
---
## Mode B: Reasons (the proven wrapper, a new reason to care)
### Concept DNA: the mechanism, not the content
Every element of the original ad is either **mechanism** (why it works; reusable with any pain) or **content** (what it happens to be about this time). The test for each element: **would it still work if the pain were different?** Yes → mechanism, locked. No → content, it changes with the angle.
Example: the "Calmly" concept C1, a 15 s UGC storytime for a sleep app (fictional).
| Element | Mechanism (locked) | Content (changes with the angle) |
|---|---|---|
| Format | storytime confession, selfie at arm's length, quiet honest voice | where she is and why |
| Hook | combined: a physical drop at frame 0 + a confession line in the shape "I tried every…" | what she drops onto, the words |
| Structure | hook → old way (three failed tries in fast cuts, closer each time) → the app as the last try → result on the person → soft spoken CTA | the three tries, the feature, the result |
| Timing and pacing | beats 0 to 2.5 / 2.5 to 6 / 6 to 10 / 10 to 13 / 13 to 15 s; a cut about every 2.5 s | none |
| Camera | handheld front camera at arm's length; one B-roll shot for the result | the place it's filmed in |
| Person | Mia, 21 (the same face in every angle) | her outfit and state follow the situation |
| Look | raw UGC, motivated practical light, brand palette | the light source of the new place |
| Audio role | native speech, no music, room tone | the room tone of the new place |
| App moment | screen turned toward her, then the result shown on the person | which feature, which screen |
| CTA and end card | soft spoken tip + store-style end card | none (the Pocket stays) |
| Emotional tone | tired, honest, a bit ironic | none |
Write the DNA from the original's own evidence (the workflow's prompts and Video Editor timings, the video's frames and transcript), never from a memory of what the ad was "about". If `lyra-copy-competitor-ad` Reference K is filled for the original, its `hook_type` and `narrative_arc` usually name the team-level concept (Authority figure, POV, Before/After).
**From Lyra's Creative Analysis (Pattern Import) output.** When the original was run through the node, its Creative Anatomy fills most of the DNA; sort its fields like this:
| Creative Anatomy field | In the DNA |
|---|---|
| Format · Layout · Text placement · Narrative structure · Hook mechanism · Motion · Pacing · Image style · Emotional register · Typography | mechanism (locked) |
| Key elements · Hook text · Objection handling | content (changes with the angle); the person in Key elements stays in mode B |
| Value proposition · Offer · CTA | the Pocket (stays), unless the angle is another feature |
| Dominant colors | the look (stays) |
| Concept summary | the original's one-line idea: rewrite it per angle for its brief |
| Notable techniques | the first candidates for "why it works" |
| Additional observations | flags for review (compliance, claims) |
The node works from frames about every second plus the transcript; anything it didn't see is a gap to fill from the workflow's prompts or to ask about, never to guess.
**Why it works** in 2 to 3 lines: what every angle must keep alive ("the pain lands in 2 s in her own words; the three failed tries are the viewer's own history; the result is shown on the person, no screen needed"). If nobody can say why it works, ask the user for the numbers and what they think won.
### The angle: a new reason to care
An angle in mode B is the reason this viewer should care now. One angle per ad. Every angle comes from the Brand Kit (the pain map, `lyra-video-hooks` Step 1), best organised per segment as **motivation layers**: what they fear, what frustrates them, what they want. A real feature answers it.
| Angle type | What it answers | Example (Calmly, students) | Watch out |
|---|---|---|---|
| **Another pain** | another problem the app solves | exam week, the brain won't stop | one pain per ad |
| **Another moment** | the same need at a new trigger moment that makes a new story | Sunday night, dreading Monday | a new story, not the old one re-dressed (that is audience variations) |
| **Outcome / desire** | the result they want | waking up before the alarm, actually rested | the result shown on the person; no invented numbers |
| **Identity / future self** | who they want to be | "the friend who's fun at brunch because she slept" | aspiration, never shame |
| **Through other people** | a partner, roommate, kids or boss notice | the roommate: "you stopped scrolling at 3 am?" | others never mock |
| **Objection** | why they hesitate | "I thought sleep apps were just rain sounds" | the body answers the doubt with the real feature |
| **Old way / alternative** | what they do now and why it fails | the third coffee, ten alarms, a podcast that keeps her awake | generic objects only; never a competitor or a brand |
| **Another feature** | a second real feature and the pain it answers | sleep sounds for a loud dorm | a new screenshot; one feature per ad |
| **Cost of the problem** | what it costs to keep the pain | "third coffee by noon and still useless" | real stakes, no fear-mongering |
| **Occasion / season** | a calendar moment that sharpens the pain | exams, jet lag after a trip, the New Year reset | fits the launch window; dated angles expire |
| **A belief to break** | a belief that keeps them stuck | "counting sheep keeps you awake" | true, no pseudo-science (in team terms this is close to the Myth-busting concept: in mode B it only changes the reason, not the wrapper) |
| **Awareness shift** | the same wrapper for another awareness level | unaware: a relatable 2 am moment with no pitch; product aware: objection first | the awareness table in `lyra-video-hooks` |
### The situation: where the new angle happens
A new angle usually needs a new situation: the place and moment where **that** pain happens (`lyra-ugc-video`, Place). Derive it from the angle, never pick a place because it looks good. The situation fills the concept's slots: the hook's physical beat happens in the new place (she drops onto the pillow → she drops her head onto the open textbook), the old-way beat gets the new angle's own tries (tea, earbuds, counting → the third coffee, an energy drink, flashcards in bed), the result happens in the new place.
| Distance | What changes | What reruns | Use when |
|---|---|---|---|
| **1. Re-angle** | the words and the app moment; the same place and person | clip(s) + VO; usually no new images | the cheapest test; the original place also fits the new angle |
| **2. Re-situate** (default) | the angle + its situation: new place, moment, props, light; the same person | scene image(s) + clip(s) + VO | the new pain lives somewhere else |
| **3. Re-story** | the angle + a new plot inside the same structure (another cause, another turning point, a second person in a skit) | as 2, plus a second character if needed | story formats: skit, micro-drama, interview, talking object series |
**Distance 1 is the riskiest for delivery.** The same person, place, shots and rhythm with new words can read to the platform as the same ad (Meta groups near-identical creatives), and Lyra's own rule for new videos is that "a talking head about fees after five talking heads about fees is not new". Use distance 1 to test the message itself; for a round that must also refresh delivery, prefer distance 2 or 3, so the first frames look different.
### The same person, by default
In mode B the person stays: the face is part of the proven wrapper, and changing it too would mix two tests (angle and person). Their outfit, state and props follow the new situation (the one-story test). Change the person only when the new angle really belongs to another segment's life; then name it an angle + audience version, or run the angle with the same person first and the person later with `lyra-audience-variations`. A recurring face across angles also turns the concept into a series the audience recognises. (When the new person *is* the point, that is mode A.)
**The sibling test (mode B):** muted, with the faces blurred, is it obviously the same concept as the original (same rhythm, same shot types, same format)? Read as transcripts, are they obviously two different ads? Is every word true for the app?
---
## Step 1 additions: the source, the mode, the angle bank
1. **The source.**
- **A Lyra workflow** (built with our skills, or the user's own): `list_variations` and `get_workflow` on the original. Read every prompt: the script note, the character, scene images and keyframes, phone shots, clips (camera, cuts, sound line, voice anchor, avoid line), VO, music, and the Video Editor's composition (the beat timings from `startMs` and `durationMs`).
- **A finished video, the user's own ad** (a file or a public direct link): `create_upload` → `attach_upload`. Analyse it as in `lyra-copy-competitor-ad` Path 2 (frames every 3 s and at each cut, transcript with timestamps) and write its layer 2 production breakdown; layer 1 (Reference K there) is optional but names the mechanism in the team's terms. It is the user's footage, so a still of the person can be the identity reference.
- **A concept name or a brief only** (mode A) → no source ad needed; angle 1 is built with the matching skill (base, UGC, UI), the next angles as variations of it.
- **A competitor's ad** → `lyra-copy-competitor-ad`.
Check `list_uploads` first.
2. **The proof.** Ask in the same message: is it a validated winner? Its numbers, if known (hook rate, hold rate, CTR, cost per trial, how long it ran)? What does the user think won? If the account has Lyra's analytics, use its labels as they are: **winner** or **near winner** (close to the best) can be a mode B base; **middle** or **loser** is not a base to patch but a starting point for mode A or a new concept; **early read**, **under-tested** or **not judged** prove nothing yet. Mode B on an unproven ad multiplies a guess: say it once and offer mode A, hooks first or a smaller round. Compare only ads of the same optimisation goal (installs with installs, purchases with purchases).
3. **The mode** (the question above, plain words, with a recommendation). Nothing in Steps 4 to 6 is written for both modes unless the user wants both rounds.
4. **Brand Kit and the pain map** (base Reference I; `lyra-video-hooks` Step 1; several kits → ask which; never mix two). Read: audience and segments, pains in their words (fears, frustrations, desires per segment), objections, features, approved claims and proof, forbidden claims, offer, tone, must include / must exclude. Mark the angle the original already uses. No pains in the kit → 3 to 5 pain hypotheses to confirm, and keep moving in the same message.
5. **The angle bank** (user text node "Angle bank"), in the team's angle sheet format, one row per angle:
| Angle ID | Concept | Angle (6 to 7 words) | Segment | Benefit · register | Bucket | Evidence | Closest ads · what's different | Flag for review | Mode A: who / lens · audience check · hooks planned | Mode B: situation · distance · hook line (words) |
|---|---|---|---|---|---|---|---|---|---|---|
- **Angle ID** `C01-A1`, `C01-A2`… (the concept number and the angle number; A1 is the original's angle).
- **Benefit:** the one benefit of the app this angle sells, a different one for every angle until each is used ("simple checkout" is one benefit, however it is filmed). **Register:** emotional (how it makes them feel), practical (what it does for them), identity (who it makes them) or critical (what is wrong with what they do now); a round spreads across registers.
- **Bucket:** **Adapt** (backed by evidence: the Brand Kit, reviews, research, past results) or **Explore** (no direct evidence yet, a bet).
- **Evidence:** the source in a few words ("KB: day-14 drop-off", "Research 2026-10-18: r/loseit 'fed up of tracking'", "reviews: 'my roommate noticed'"); with Lyra's analytics, how many of the account's ads already back it ("3 ads, one a winner") and Lyra's tag verdict if there is one (ads with it get results for less, in the same goal).
- **Closest ads · what's different:** up to 3 ads the account already ran that are most like this angle, and what makes this one different. Nothing → drop the angle. A similar ad that lost → say what is different this time.
- **Flag for review:** what a person must check (a claim, a stat to cite, a sensitive topic, a real review needed).
- Never repeat an angle already proposed or already run for this account (check the project's creative repository and earlier angle banks), in any wording.
Mode A, examples:
> C01-A2 · Authority figure · A teacher gives movement as homework · students and parents · Explore · no direct evidence · flag: playful role, no claims · who: a teacher in a classroom skit · 5 hooks
> C01-A3 · Authority figure · A trainer shares what clients get wrong · goal-driven gym-goers · Adapt · KB: gym-goer pains · flag: none · who: a trainer, insider, no titles · 5 hooks
Mode B, examples:
> C01-A2 · Storytime confession · Exam week, the brain won't stop · students · Adapt · KB: exam stress in reviews · situation: her desk at 1 am, notes and highlighters, only the desk lamp · distance 2 · hook: "I tried every way to sleep in exam week." (9)
> C01-A3 · Storytime confession · Sleep apps are just rain sounds · students who tried apps · Adapt · reviews: "finally not just rain sounds" · situation: the same bed at 2 am · distance 1 · hook: "I tried every sleep app that's just rain sounds." (9)
> C01-A4 · Storytime confession · The roommate notices she sleeps now · students in shared rooms · Explore · no direct evidence · situation: dorm room in the morning, the roommate at the door with two coffees · distance 3
8 to 12 rows. Recommend: mode A, 3 to 4 angles (2 to 3 for a first round); mode B, 3 (2 to 4). One line why; at least one Adapt close to the original (safer) and one Explore further away (more learning).
6. **Intake quiz** (base Step 1 format: one message, multiple choice, options from the Brand Kit, the recommended option first): the mode · which angles (with your recommendation) · how many (and in mode A, hooks per angle) · in mode B, the same person (default yes) · screenshots of any new feature · language · anything the brand doesn't want to say or show.
**Defaults (state, don't ask):** mode B for a validated winner, mode A for a concept name or an early concept · mode A: 3 angles × 3 hooks for a first round · mode B: 3 angles + the original as control, distance 2, the same person · **one variation per angle**, copied from the original, which stays Main and untouched · the same length, ratio, platform and models as the original · same music, CTA, offer and end card · real people: Seedance 2.5, references only, the original's resolution (720p by default), sound on · Nano Banana Pro for every image, 9:16, 2K.
**Recommended first run:** A. Images (mode A: each angle's person and scene; mode B: each angle's new situation). Images are cheap, and they show whether each angle reads in one glance.
---
## Step 2 addition: the multiplier sheet
Before building, a user text node "Multiplier sheet", part of the concept the user approves.
**Mode A:**
1. **The concept card** (above) and the **lock list**: the Pocket (CTA, offer, end card), the brand look and palette, the length and ratio, the format family if the user wants one.
2. **One angle card per angle:** the perspective in 6 to 7 words · the person (character card, `lyra-ugc-video`) · the place and moment · the argument in one line (what this perspective says that the others don't) · the spine with times (hook → the point → the app → CTA, by the base skill or the format's skill) · the feature it shows · the 3 to 5 hook ideas (one line each, approved before writing them out).
3. **The tree** (concept → angles → hooks) with codes, as above.
4. **Hypotheses:** one line per angle.
**Mode B:**
1. **Lock list:** what stays identical in every angle, from the DNA: format, beat jobs and timing (about ±0.5 s per beat), hook mechanism, camera setup and moves, cut rhythm, the person, look and palette, audio role, voice anchor, music, CTA, offer, end card, length.
2. **Situation card** per angle: the angle · the moment (time, day) · the place with 2 to 3 lived-in details · the light source · props · the person's state and outfit · the feature and its screen. Name the place, props and actions concretely, the way Lyra's tag mapper reads them: a **scene** ("living room", "street"), **objects** with an attribute ("wooden box", "pink nail polish"), **actions** ("scanning a coin with a phone"). Mood words ("serene", "cosy") are not tags and count for nothing; they belong in the prompt's light and tone, not in the card's list of what changed.
3. **Beat sheet, side by side:**
| Beat | Time | Job (locked) | Mechanism (locked) | A1 (control) | A2 exam week | A3 objection |
|---|---|---|---|---|---|---|
| Hook | 0 to 2.5 s | stop, name the pain | a physical drop + "I tried every…" | drops onto the pillow: "I tried every sleep hack on TikTok." (8) | drops her head onto the textbook: "I tried every way to sleep in exam week." (9) | drops onto the pillow, phone up: "I tried every sleep app that's just rain sounds." (9) |
| Old way | 2.5 to 6 s | the viewer's own failed tries | three tries, fast cuts, closer each time | tea, earbuds, counting on her fingers | a third coffee, an energy drink, flashcards in bed | rain, whale sounds, a meditation |
| App | 6 to 10 s | the last try | screen turned toward her, one line | "This one does a 5-minute wind-down." | same | "This one actually talks you down. Five minutes." |
| Result | 10 to 13 s | result on the person | B-roll, eyes closed | asleep, phone face down on the duvet | asleep, notes stacked on the chair, alarm set for 7 | asleep, headphones off |
| CTA | 13 to 15 s | soft tip | back to the selfie, smile | "It's free. Try it tonight." | same | same |
Word counts per line within about ±10% of the original (never past ±20%, Lyra's Ad Variation limit); the same level of claims.
4. **Hypotheses:** one line per angle.
**Both modes, per angle: Changed fields, Held constant, and a brief in Lyra's format.**
- **Label** the angle by its strategic idea ("Exam-week pain", "Teacher's homework"), never "Variant A".
- **Changed fields:** every dimension that changes, from → to, concretely (Person: Mia, 21 → Ana, 29, a nurse · Place: bedroom at 2 am → desk at 1 am · Hook line: "…" → "…").
- **Held constant:** every dimension that does not change, listed one by one, not "everything else". In mode B this is the lock list; in mode A at least the Pocket, the brand look and the length.
- **Brief** (a user text node "Brief: C1A2"), in the exact format of Lyra's Ad Brief node, so it reads like every other brief in the workspace: `aspect_ratio` (9:16, 16:9 or 1:1) · `elements_to_include` (the production blocks: voiceover, music, brand video asset… only what the angle needs) · then three sections with their labels written exactly: **Concept Hypothesis** (Statement · Concept angle, up to 100 characters: the whole idea in one phrase · Format type) · **Creative Direction** (Concept summary, 200 · Hook mechanism · Hook suggested text, 80 · Value proposition, 150 · Proof point, only a real one · Tone · Offer text · CTA text, 30) · **Visual Direction** (Format · Layout Description, 200 · Image Style · Color Palette Primary · Duration seconds · Must include elements · Must exclude elements). A field with nothing real for it is left out, never "N/A".
---
## Writing the new script
**Both modes:**
- **One angle, one feature, one result** per ad. The CTA and offer stay identical (the Pocket); an angle-specific CTA only when the offer is part of the angle, named in the plan.
- **Hooks** follow `lyra-video-hooks` (6 to 10 words, key word first, text on frame 1 of 2 to 6 words, marked for post).
- **Captions** are written to the new words, marked for post (Video Editor only, never in a prompt).
- Base pace about 2.5 words per second; speech ends about 1 s before the clip ends.
**Mode A:** each angle gets its own script on the concept's spine, in its speaker's voice, with its own argument. Within an angle, all hooks share one body; the body is written once and the hooks are cut onto it (hooks skill, mode A). Across angles, keep the length and the Pocket the same so the angles compare fairly.
**Mode B:**
- Beat by beat, from the beat sheet. Each line keeps its **job** and, where the shape is part of the mechanism ("I tried every…", "POV: …", a list of three), its **shape**; the words are new, built from the Brand Kit and customer words.
- **Timing contract:** the same beats in the same order, each within about ±0.5 s of the original, the same total length.
- **A beat that doesn't fit the angle** (an outcome angle has no "three failed tries"): give the beat new content with the same job and the same length (three moments of the tired morning before, three alarms snoozed), or drop that angle. Never break the timing contract or the beat order to force an angle in: that is mode A or a new concept.
---
## Best way to build it
The user's explicit choices override any row. Models and prices: base Reference A.
| If | Best approach (graph) | Models |
|---|---|---|
| **Mode B, a Lyra workflow with a finished creative** (default for B) | **one variation per angle** (below): `create_variation` → `switch_variation` → the character node keeps its copied result (the identity) → the scene image(s) rewritten for the new situation, with the character connected as reference → the clip prompt: content lines replaced, locked lines word for word → new VO text if the VO is separate → rerun only the changed nodes → Video Editor with the same timings | as the original |
| Mode B, **distance 1** (re-angle, same place) | variation → `update_node` on the clip's speech and app moment, and the VO; the images stay | as the original |
| **Mode A, a built ad as angle 1** (default for A) | one variation per angle: a new character node or prompt (the angle's person, count 2) → the angle's scene image(s) with that character as reference → the body clip on the concept's spine with the angle's script → the angle's hooks by `lyra-video-hooks` mode A (one Section per hook inside the variation, each with its own Video Editor) | nano-banana-pro · seedance-2.5 |
| Mode A, **a concept name only** | `create_workflow` → angle 1 built with the matching skill (UGC, base, UI) → then one variation per further angle, as the row above | as the matching skill |
| The angle shows **another feature** | + `create_upload` of the new screenshot → phone shot by `lyra-ui-motion-video` (screenshot + character) → reference for the clip, or a short UI insert in the Video Editor | nano-banana-pro · seedance-2.5 / 2.0 |
| A workflow on **frame models** (Seedance 2.0, Kling) | a new keyframe per shot (character as reference; mode B: the old keyframe's framing written in words) → the frame linked right after the image has a result and the user selected one | nano-banana-pro · seedance-2.0 / kling-v3-video |
| **A finished video** (the user's own), no workflow | DNA or concept card from the breakdown → mode B: a still of the person as the identity reference; mode A: a new character per angle → per angle: scene image → **one Seedance 2.5 clip** with the shot plan as "cut to" with lengths → optional in mode B: the original as **[Video1], editing reference only**, when the timing must match closely; check that the old place and words don't leak → VO and music → Video Editor | nano-banana-pro · seedance-2.5 |
| **Story formats** (skit, micro-drama, interview, talking object series) | mode B distance 3: the same characters and roles, one new episode per angle, the same episode structure and length · mode A: a new character or role per angle in the same format | seedance-2.5 (people) · seedance-2.0 (stylized) |
| **A visual hook concept** (object POV, fourth wall, visual metaphor) | the mechanism stays, the object moves into the new situation (the fridge camera → the gym bag camera; the giant heavy head → a giant stack of flashcards) | as the original |
| **A UI motion concept** | the style, motion vocabulary, layout and end card stay; the angle changes the headline and the screen (another feature, another benefit), by `lyra-ui-motion-video` | as the original |
| An angle that needs its own workflow (another client, shared separately) | workflow menu (⋮ next to the name) → **Save as a new workflow**; no MCP tool does this, so ask the user to click it (or do it in their browser if they allow), then work there | as the original |
| Many angles, tight budget | mode B distance 1 angles first; mode A 2 angles × 3 hooks; images for all, clips only for the 1 to 2 the user picks; or drafts on a fast model and the winner on the recommended one | seedance-2.0-fast for drafts |
### Variations: the way to make an angle
In Lyra every version of a creative is a **variation** of its workflow: the **Create variation** button above the canvas (the `create_variation` tool) copies the whole space (every node, prompt, connection and result). The original stays **Main** and untouched as the control (angle A1); the new angle is written into the copy.
**Step by step:**
1. `list_variations` → find the original (the main one, unless the user names another). Rename it if needed: `rename_variation` "C1 · A1 · storytime · can't sleep (control)".
2. Put the notes ("Concept card" or "Concept DNA", "Angle bank", "Multiplier sheet") in the original's Sources Section before copying, so every variation carries them (notes don't feed generation).
3. `create_variation` with `copy_from_variation_uuid` = the original and `title` = code, angle, person or situation, language: "C1 · A2 · teacher · EN", "C1 · A2 · exam week · desk · EN". The copy carries the original's results, so what doesn't change (music, end card, screenshots, and in mode B the character) never reruns.
4. `switch_variation` to it (Lyra renames the workflow after the main variation; tell the user which one is open), then `get_workflow`.
5. Write the angle in with `update_node`, by the node map below. New nodes if needed (a character in mode A, a scene image, a new screenshot upload, a phone shot, hook clips and their Video Editors), connected at build time with `connect_nodes`; `disconnect_nodes` an image of the old place or old person from the clip if it would pull them in.
6. `get_workflow` on the variation and search every prompt for the old angle: the old pain words, the old place, old props, old lines, and in mode A the old person. One forgotten line puts two ads in one.
7. Read the price on the nodes that will rerun and put it in the approval message (base Step 6: one question, then run everything). Unchanged nodes keep the copied results.
8. Repeat from step 3 for the next angle (always copy from the original, never from another angle).
9. When done, `switch_variation` back to the original if the user wants it shown first, and say which variation holds which angle.
### The node map: what to update, what reruns
| Node | Mode A (new perspective) | Mode B distance 1 (re-angle) | Mode B distance 2 (re-situate) | Mode B distance 3 (re-story) |
|---|---|---|---|---|
| Character (identity) | new person for the angle: rewrite and rerun (count 2) | stays, result copied | stays as the identity reference; the new outfit and state go into the scene image prompt | stays; a second character added if the plot needs one |
| Scene images, keyframes | the angle's place, with the new character as reference → rerun | stay | new situation: `update_node` (or a new node with the character as reference) → rerun | as distance 2 |
| Screenshot, phone shot | new if the feature changes; a phone shot with a new person reruns | stay, unless the feature changes | same | same |
| Clip(s) | the angle's body: identity, place, action, speech, voice anchor rewritten; camera and length from the concept's spine | content lines: speech, app moment | content lines: environment, props, light, the action's content, speech, app moment | + plot lines, who says what |
| Hook clips | about 5 new per angle (hooks skill) | — (the hook line is in the main clip) | — | — |
| VO (if separate) | new text and a voice that fits the new person | new text, same voice and length | same | same |
| Music | stays (new only if the perspective's emotion really differs; say why) | stays | stays | stays |
| End card, logo | stay | stay | stay | stay |
| Video Editor | one per hook inside the angle | reruns with the same timings; captions changed in the editor UI | same | same |
**Mode B: never rerun the character node** to "refresh" it: a new run is a new face, and the series loses its person. Keep the copied result and pass it as a reference.
**Mode B locked lines in a clip prompt** (copied word for word from the original): the roles of the references, the camera setup and moves, the cut structure and lengths ("cut to" with times), the sound line (if someone speaks and the original's lets music in, add "no music, no background music, no soundtrack, no score": base Reference C), the voice anchor, the end state of each shot (only its place details adjusted), the avoid line. **Content lines** (rewritten): the environment, props, light source, the content of the action, the spoken lines in quotes, the app moment.
**Connections.** A variation copies the original's connections, so the graph already runs end to end. Only new nodes need links (base Step 4): a new character → every image and clip that shows the person; a new scene image → the clip as a reference; a new screenshot → the phone shot → the clip; hook clips → their Video Editors; on frame models, the new keyframe right after it has a result. The text notes don't feed generation; consistency comes from the images connected as references plus the anchors written into every prompt.
**Layout and labels.** Each variation keeps the original's layout, Sections and order, so the user can flip between angles and see the same canvas. Mode A adds one Section per hook. Relabel the nodes that changed with the angle code: "A2 teacher: character", "A2: classroom (scene)", "A2: body clip", "A2H3: homework squats (hook clip)", "Final: C1A2H3 · teacher homework", "A2 exam week: desk (scene)", "Final: C1A2 · exam week".
---
## Prompt rules (concept multiplier)
| Node | Write | Avoid |
|---|---|---|
| Concept card / Concept DNA (text) | mode A: the concept in 3 to 4 words, its mechanism, why it works, the lock list · mode B: element by element, mechanism (locked) and content, why it works, beat slots with times and jobs | what the ad is "about" without naming the mechanism |
| Angle bank (text) | the team's angle sheet: ID, concept, angle in 6 to 7 words, segment, bucket, evidence, flag; plus the mode's columns | one angle reworded several times; an angle without a real feature or a segment |
| Multiplier sheet (text) | mode A: angle cards and the tree · mode B: lock list, situation cards, beat sheet with word counts; hypotheses | "a different vibe" without naming the angle |
| Character (mode A) | the angle's person in the structure of Lyra's Character Prompt node (a note per angle): **Character** (age range, gender, ethnicity) · **Appearance** (build; hair: colour, length, style; face details with small imperfections; distinctive features) · **Style** (outfit, style vibe, accessories) · **Behavior** (expression, natural and subtle; pose, selfie or direct to camera; action tied to the app) · **Environment** (a specific real location, context, natural imperfect lighting, camera feel: front camera, handheld) · then the image prompt: up to about 500 characters, subject first, camera angle, environment, action, light, with the words "natural", "realistic", "UGC style", "not polished" · and the negative prompt, always with "studio lighting, overproduced, perfect skin, model look, cinematic, 3d render, illustration, text overlays, watermark, blur, distortion". A role is shown by the situation and props, not by titles | a white coat with a stethoscope as proof; "Dr." or job titles in text; a lookalike; a stereotype or caricature of the role |
| Scene image (mode B, same person, new situation) | "UGC phone photo" → "[Image1] is [name]: keep the face, hair, skin and build exactly" → the new situation in full: place, moment, 2 to 3 lived-in details, light source, props → outfit and state that fit it → the original shot's framing and camera setup, in words → realism line → no text | "the same scene, but in a library" (keeps the old room); details of the old place; text, logos, brands |
| Clip | mode A: the concept's spine and camera told in words, the angle's identity, place and speech · mode B: the original prompt with content lines replaced, locked lines word for word; roles of references first | mode B: another camera, cut structure or timing; the old place, person or words left anywhere |
| VO | the new text, sized to the original's length | a VO longer than the clip minus 1 s |
| Music | unchanged by default | a new track "for variety" (it breaks the comparison) |
**Pattern: scene image, same person in the new situation (mode B, Nano Banana Pro, distance 2).**
> UGC phone photo, same person in a new place. [Image1] is Mia: keep her face, hair, skin texture and build exactly. She sits at a cluttered desk in her student room at 1 am, her head resting on an open textbook, highlighters and three empty coffee cups around her laptop, flashcards spilling onto the floor; the only light is a warm desk lamp and the glow of the laptop. Grey hoodie, hair in a loose bun, tired eyes. Shot on a phone front camera at arm's length, slightly above eye level, the selfie framing of a storytime video, deep focus, natural skin texture, visible pores, slight dark circles, no beauty filter. No text, no captions, no watermark, no logos, no visible phone screen.
**Pattern: what changes in a clip prompt (mode B, Seedance 2.5).**
> Locked, word for word: "[Image1] is Mia: her face, hair and grey hoodie. [Image2] is the scene. Handheld selfie at arm's length, front camera, slight natural wobble… cut to (2.5 s)… cut to (3.5 s)… Sound: only natural room tone and action sounds, no music, no soundtrack, no score. Voice: young woman, soft American accent, sleepy, unhurried. Avoid: morphing faces, identity drift, outfit change, warped hands, text on screen."
>
> Content, new: "She drops her head onto the open textbook, looks up into the camera and says: 'I tried every way to sleep in exam week.' Cut to: a third coffee, closer. Cut to: an energy drink, closer. Cut to: flashcards in bed, closest…"
**Pattern: a mode A angle character (Authority figure → the teacher, Nano Banana Pro, in the Character Prompt node's format).**
> Prompt: Woman in her early 40s, a teacher, warm brown skin, short natural hair, reading glasses pushed up, cardigan over a plain blouse, front-facing selfie at arm's length in an empty classroom after school, whiteboard behind her with a stick-figure doing squats, she raises her eyebrows about to give homework, late afternoon window light, natural, realistic, UGC style, not polished, visible skin texture.
>
> Negative prompt: studio lighting, overproduced, perfect skin, model look, cinematic, 3d render, illustration, text overlays, watermark, blur, distortion, readable text, logos, name badge.
---
## Run options (concept multiplier)
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes, per option. **Mode A:** **A. Angle images (recommended):** each angle's person (count 2) and scene · **B. Angle bodies** for the picked people · **C. Hook clips and Video Editors** (about 5 per angle, or the 3 the user picks) · or **D. Everything** at once (count 1; no pause to pick). **Mode B:** **A. New scene images (recommended):** every angle's situation · **B. Clips, VO and Video Editors** for the picked images · or **C. Everything** (count 1). Mode B distance 1 angles skip A and cost only the clip and the VO. When an image has several results, the user selects one in Lyra before the next stage (references pin to the selected result).
---
## Truth and brand safety
- **Every angle is real.** A pain or desire from the Brand Kit (or a confirmed hypothesis), answered by a feature the app really has. An angle the app can't truthfully answer is dropped, however good it sounds. Explore angles are bets, not claims.
- **No new claims.** A new angle never brings a new result, number or promise ("I passed my exams thanks to Calmly"); claims stay at the original's level, from the Brand Kit only. The promise matches the store page and the first session.
- **No fake experts.** An AI person is never a real doctor, coach, advisor or reviewer: no titles, credentials, white-coat proof or professional advice (health, money, law). Authority angles are playful roles, insiders without credentials, parents and friends, or a real expert the brand works with, with consent. Remind the user once to turn on the AI-generated label (`lyra-ugc-video`, Truth and disclosure).
- Sensitive categories: health, sleep, fitness, finance angles promise no cure, weight loss, diagnosis or returns; no body before/after.
- No personal-attribute callouts to the viewer (Meta's personal attributes policy): the person speaks about their own life ("I'm on nights this week"), never "Are you anxious?". Check the current platform rules; this is not legal advice.
- Stakes, warning and fear angles use real stakes, no fear-mongering; myth and belief angles are true.
- No third-party brands: the old-way beat shows generic objects (a coffee cup, an energy drink can without a brand, "a sounds app"), never a competitor, a named product, a logo or readable packaging; no "if ChatGPT is your coach" style callouts of other products unless the brand's team approves. Occasions are generic (exams, a trip, the New Year), never a trademarked event.
- **Brand safety** (Lyra's System Preamble, base Reference B): no profanity and no political statements in any angle (health claims and competitors are covered above). The Brand Kit's **forbidden claims are enforced absolutely**, in every angle's line, caption, visual and VO; if the user asks for one, say once that it is on the kit's forbidden list and leave it out unless the user confirms the kit is outdated.
---
## Deliverable and naming
1. The notes in the original's Sources Section: "Concept card" (mode A) or "Concept DNA" (mode B), "Angle bank", "Multiplier sheet".
2. One variation per angle (titled with its code, angle, person or situation and language), with its changed images, clips, VO and Video Editor(s); the original untouched as Main, the control (A1).
Codes follow the tree: concept `C`, angle `A`, hook `H`. The angle sheet uses the team's ID `C01-A2`; the ad name uses the short form `C1A2` (+ `H3` for a hook). Each angle puts its own angle in `A:`: control `B6-A:CantSleep-F:UGC-Storytime-C1A1` → mode B `B7-A:ExamWeek-F:UGC-Storytime-C1A2`, `B7-A:JustRainSounds-F:UGC-Storytime-C1A3` · mode A `B7-A:TeacherHomework-F:UGC-Skit-C1A2H3`. Add `V{n}` for audience variations of an angle: `…-C1A2-V4Bundle-Nurses`. Mark the round when both modes run: `…-C1A2-ModeA`, `…-C1A2-ModeB`. Node label: "Final: C1A2H3 · teacher homework".
---
## Common mistakes (concept multiplier)
| Mistake | Prevention |
|---|---|
| The mode not asked, or asked in abstract words | The plain-words question with the user's app and an exaggerated example of both modes |
| "Angle" means one thing to the user and another in the build | Say the mode's meaning in one line in the plan |
| Mode A: a new speaker quietly changes who the ad is for | The audience check per angle: same situation and goal, or a named new-persona angle |
| Mode B on a middle or losing ad | Bases are winners or near winners; the rest start mode A or a new concept |
| A round of distance 1 angles only, read by the platform as the same ad | Distance 2 or 3 when the round must refresh delivery |
| Angles that share a benefit, or all in one register | One benefit per angle; spread across emotional, practical, identity, critical |
| No "closest ads" checked, so the angle repeats what already ran | Closest ads and what's different in every row |
| A Lyra hypothesis card for a new video built as a variation of an old one | `new_angle`, `new_persona`, `new_concept` are invented videos (base skill); multiply them once they win |
| "Variant A", or "everything else stays" without the list | A strategic label; Changed fields and Held constant listed one by one |
| An angle judged on click rate, install rate or CPM | Cost per result of its goal; click rate alone is clickbait, install rate is the store page, CPM is delivery |
| Mode A: hooks written before the angles are approved | Angles first, hooks after |
| Mode A: 20 videos built in one go, the budget gone | 2 to 3 angles × 3 hooks first; more for the promising angles |
| Mode A: an AI "doctor" with titles giving advice | Playful role, insider, parent or a real expert; no credentials, no advice |
| Mode A: the new person says the old script (that's audience variations) | Each angle has its own argument and script |
| Mode B: the DNA describes the topic, not the mechanism | The element table: mechanism vs content, the "would it work with another pain?" test |
| Mode B: the format, beat order or hook mechanism changed "so the angle fits" | That's mode A or a new concept; pick an angle that fits the wrapper |
| Mode B: the person changed with the angle (two tests in one) | The same person; audience variations later |
| Mode B: the character node rerun, so the face changed | Keep the copied result; pass it as a reference |
| Nobody knows why the original works | Ask for numbers and the user's view; say once that an unproven ad multiplies a guess |
| Angles invented without reading the Brand Kit, or with no segment and evidence | The angle sheet: segment, bucket, evidence for every row |
| Only Adapt (safe) or only Explore (bets) | Mostly Adapt, one or two Explore |
| Three angles that are one angle reworded | Different perspectives or reasons, different situations |
| An angle the app can't truthfully answer, or a borrowed feature | One real feature per angle; no fit → drop the angle |
| The place chosen because it looks good | The angle's pain moment picks the place |
| "Same scene, but in a library" in the prompt, so the old room stays | Describe the new place in full; the character image is only for identity |
| An old place, person, prop or line left in a node | `get_workflow` on the variation; search every prompt for the old angle |
| Timing drifts, or the new VO is longer | Mode B timing contract (±0.5 s per beat, words ±10%); VO ≤ clip − 1 s |
| A new claim arrives with the angle | Claims identical across angles, from the Brand Kit only |
| Music, CTA, offer or end card changed "for variety" | The Pocket and the music stay |
| The original edited instead of a variation | Original untouched as Main; `create_variation` per angle |
| A variation copied from another angle | Always copy from the original |
| A competitor or brand named in the old-way beat | Generic objects only |
| "Are you exhausted?" in the hook | First person about their own life; situation callouts only |
| A competitor's ad used as the source | `lyra-copy-competitor-ad` first |
## Quality gates (concept multiplier)
- **Stage 0 (notes; Claude checks before sending):** the mode asked in plain words and picked by the user? Every angle in the angle sheet with a segment, bucket, evidence and a one-line hypothesis, answered by a real feature? Angles really different? **Mode A:** concept card with its mechanism; angles in 6 to 7 words; each with its own person, place and argument; hooks only after the angles are approved; no fake experts; budget sized (angles × hooks)? **Mode B:** DNA element by element with why it works; situations derived from each angle's pain moment; lock list; beat sheet with the same jobs, order and timing, word counts about ±10%; the same hook kind and mechanism? Both: no new claims, no personal-attribute callouts, no brands?
- **Stage 1 (images):** mode A: each angle's person reads as that perspective in one glance, natural, no titles or logos? Mode B: the same person as the original, the new situation reads at thumbnail size, the original's framing kept, no trace of the old place? Both: hands, phone and screen right (the screen identical to the screenshot)? No readable text? As phone-real as the original?
- **Stage 2 (clips):** mode A: each angle's body tells its own argument; the hooks of one angle cut cleanly into its body? Mode B: the beats and timing match the original, the same camera and cut rhythm, the same voice? Both: lines said right, the app name pronounced right, the person stable through the cuts? If [Video1] was used: nothing of the old place or words leaked in?
- **Stage 3 (finals):** mode A: the angles clearly different perspectives on one concept, the same Pocket and length? Mode B, side by side with the original: muted, the same concept; read, a different ad? Both: captions match the new words, the same music, CTA, offer and end card, 9:16, the original's resolution, planned length, named with its `C·A·H` code, AI label reminder given?
## After the test
- Launch the control and the angles the same day, with the same setup and budget.
- Tag every ad with its concept, angle and hook (the codes), so results can be read **per level**: a good hook rate with a poor ROAS is a hook that works on an angle that doesn't convert, not a dead concept. Example: Authority figure × financial expert: hook rate ok, CTR decent, ROAS poor → the hook gets people in; this concept-angle pair doesn't convert them.
- Sort every ad into four groups: **Winners · Losers · Needs attention** (fatiguing, clickbait or borderline) · **Requires more data**. With Lyra's analytics, its labels and its pass mark decide: a changed video passes at least 20% below its base's cost per result, a new one 20% below the goal's usual cost (or below the video it started from, when that one is cheaper), read after 30 results in its first 14 days. Without them, judge each ad at 5,000+ impressions and by CPA / ROAS, as in `lyra-video-hooks` (After the test).
- **Judge an angle on the cost per result of its goal**, never on one rate: an angle shapes the whole ad, not one step. The steps say where it works: opening (hook rate), hold (hold rate), click (CTR). Click rate alone never makes an angle good: high clicks with dear results is clickbait. Click-to-install depends on the store page, the same for every ad, so it says little about the angle. CPM is delivery, never the angle's fault. Compare only within one optimisation goal.
- **Mode A learning:** which perspective carries the concept → more hooks on it, the winning perspective in mode B (new reasons in its wrapper), audience variations of it. **Mode B learning:** which reason sells → add it to the Brand Kit's pain map as proven; a losing angle in a winning wrapper is a clean "no" on that angle; every angle losing against the control → the original may have won for its angle, not its wrapper: go back to it with hooks.
- Expect few winners: about 1 concept in 10 becomes one, and a winner fatigues in about 4 to 8 weeks (Singular benchmark, quoted by the team). A wrapper carries several rounds of angles; when two rounds in a row stop beating the control, it is tired: time for a new concept.
- Save to the project's creative repository: concept, angle, mode, hook, segment, bucket, evidence, hypothesis, result, so the next round (and the research agent) starts from what was learned.
lyra-audience-variations41.4 KB
View saved version →
---
name: lyra-audience-variations
description: "Audience variations of a mobile app video ad in Lyra. The same ad, message and edit, with the visible world changed for another part of the app's audience from the Brand Kit, one layer or a coherent bundle at a time - the person (character swap), wardrobe and styling, setting and background, props and vehicles, time and season, market markers, voice and language, polish - each built as a Lyra variation of the original workflow. Use for \"swap the character\", \"same video with another person / another outfit / another room / another car\", \"a version for moms / men / 40+ / nurses\", \"localize for Brazil\", \"new faces or a new look for this winner\", \"test personas or settings\", \"persona A/B test\". Not for a new angle or message on the concept (lyra-ad-concept-multiplier). Core video rules come from lyra-video-ad-generation; person, voice and speech from lyra-ugc-video."
---
# lyra-audience-variations
Mini skill. Takes a video ad that works (a Lyra workflow, a finished video, or a concept about to be built) and makes versions of it for other parts of the app's audience by changing **what the viewer sees and hears**: the person, their clothes, the room, the car, the time of day, the market, the voice. The message, the angle, the script, the beats, the camera and the edit stay. One version = one Lyra **variation** of the original workflow.
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**Why it works.** In app ads, the visible world is targeting. In the first second the viewer reads who this is about from the face, the clothes, the room and the things around the person, and decides "that's me" or scrolls. The same proven message in a world that looks like another segment's life can reach people the original never stopped. And because the message stays identical, each version is a clean test of one visible thing.
**This is a way of thinking, not a script.** The rules below are defaults and good practice. Use judgment: when a different layer, bundle or build serves the audience better, do it and say why in one line. Only a few things are fixed: truth (no invented claims, reviews or numbers; an AI person is never a real customer), the Brand Kit's facts, casting ethics (no real people or lookalikes, no stereotypes, adults only as speakers), the product and its real UI, Lyra's technical limits, and the user's explicit choices.
**Base skill first.** Everything not written here follows `lyra-video-ad-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, prompt rules, models (Reference A), audio (C), app UI (D), consistency (E), prompt craft (F), errors (G), de-slop (H), Brand Kit (I), Meta app ads (J). This file only adds what is specific to audience variations. If the two disagree, the user wins, then this file, then the base skill.
**Other skills for their parts.**
- Person, place, voice, speech, camera setups, character card and realism → `lyra-ugc-video`.
- A phone moment or any UI → `lyra-ui-motion-video`: the screen never varies; a rebuilt phone shot keeps the same screenshot, checked word by word.
- New openings on a version (version × hook tests) → `lyra-video-hooks`.
- A new angle, message or story on the same concept → `lyra-ad-concept-multiplier`.
- A competitor's video as the source → `lyra-copy-competitor-ad` (their actor or world is never kept: that is a copy, not a variation).
---
## Audience variations or concept multiplier
Both keep what worked and make more versions; they answer different questions.
| | **Audience variations** (this skill) | **Ad concept multiplier** |
|---|---|---|
| Question | Who is it for? Whose life does it show? | What else can this concept say? |
| Changes | the visible layers and the voice; words only where they are tied to the person or the place | the angle (another pain, benefit or motivation), the situation as a new story, the script |
| Stays | the message, the angle, the script, the beats, the timing, the camera | the concept's mechanism: format, structure, hook mechanism, pacing, look |
| The test reads | which person or world pulls which segment | which angle sells |
**The border rule.** If the script's words change beyond the identity-bound ones (line audit, Step 2), it is the multiplier. A setting stays here when it is **the same situation re-dressed** for another audience (a bedroom in São Paulo, a nurse's bedroom at 9 am); it goes to the multiplier when it is **a new situation where another pain happens** (bed → gym).
**The ladder of iterations:** hooks (the first 3 s, `lyra-video-hooks`) → audience variations (who and where) → concept multiplier (a new angle) → a new concept (base skill).
---
## How to think about an audience variation
**Every version is a hypothesis**, written as one line: "We think [segment] stops and installs more when the ad shows [what changed], because [reason from the Brand Kit]."
**Two ways a person works** (archetypes from `lyra-ugc-video`): a **mirror** (the viewer sees themselves) or a **trusted guide** (a friend a step ahead, a converted skeptic, an insider, a parent). The world around the person works the same way: it is either the viewer's own world, or the world they want.
### The layers: everything visible that can vary
| Layer | What changes | What it tells the viewer | What reruns (cost) |
|---|---|---|---|
| **1. Person** (character swap) | face, age, gender, body type, energy, archetype | "that's me" or "I'd listen to her" | the character → every image and clip with the person |
| **2. Wardrobe and styling** | clothes, hair, makeup, nails, glasses, jewelry, bag | occupation, income, subculture, season, how put-together they are | the character (the outfit is part of the card) → every image and clip with the person |
| **3. Setting and background** | the room, the building, the street, the city; its lived-in details | life stage, living situation, market | every image and clip that shows the place |
| **4. Props and vehicles** | the car (class, age, interior), laptop or tablet, mug or mate, stroller, pet, sports gear, the phone's body | lifestyle, status, life stage, hobby | only the scenes where the prop appears |
| **5. Time, season, weather, light** | night or morning, winter coat or summer heat, rain, daylight or lamp | rhythm of life (shift worker, parent, student), market and season | every image and clip of the scene; wardrobe often follows |
| **6. Market markers** | architecture, window views, sockets, food, interiors, street look; no readable text | "this is here, this is us" | the scenes that show them |
| **7. Voice and language** | the voice (age, gender, accent, texture), the language, the identity-bound words, captions | market, age, warmth or authority | native speech: the clips with speech; a separate VO: only the VO node (the cheapest layer) |
| **8. Polish and palette** | raw or elevated, light quality, grading, palette inside the brand | mass or premium, playful or calm | almost everything |
**What never changes in an audience variation:** the product and the feature, the UI (only the user's screenshots, the same screen in every version), claims, offer and CTA, the angle and the message, the beat structure and timing, the hook mechanism. A change there is a new concept or the multiplier.
### One layer or a bundle
- **Clean variation (mode A, for tests):** one layer changes, everything else is copied word for word. The result teaches which visible thing moves the numbers: "the scrubs pulled nurses", "the premium car lowered cost per trial", "the man in his 40s beat the student".
- **Audience version (mode B, for a segment or a market):** the coherent bundle that belongs to that audience changes together (person + wardrobe + setting + time + voice and language) and is named as a version, not a clean test.
| | **A. Clean variation** | **B. Audience version** |
|---|---|---|
| What changes | one layer | the bundle that belongs to the segment or market, plus the identity-bound words |
| What stays | everything else, word for word | the message, the angle, beats and timing (about ±0.5 s per beat), camera setup, feature, CTA and offer, music, end card |
| Pick it when | testing which person, outfit, setting or prop works; refreshing a fatigued winner | a new segment from the Brand Kit, a new market or language |
| Reads as | "V2 (person) vs control V1" | "the C1 ad for nurses", "the C1 ad for Brazil" |
Both can run in one round: the original as control + 1 to 2 clean variations + 1 audience version.
**Coherence: the one-story test** (`lyra-ugc-video`). The layers still tell one life. A nurse needs the scrubs, the morning daylight and the tiredness; a student in a premium car, or a 55-year-old man with a 20-year-old's voice, breaks the story. When one layer changes, check the others: in mode A, change only what can change alone; in mode B, change everything the new life needs.
**Different enough to count.** The change must read at thumbnail size in the first second. A new T-shirt color is not a variation: it teaches nothing, and Meta's delivery tends to treat near-identical creatives as one (check the current behaviour). Make the tested difference visible at a glance.
**Final test for every version:** would someone from this segment see the first frame and think "that's me" (or "that's the life I want")? Is the tested difference obvious, and everything else the same? Is every word still true for the app?
---
## Step 1 additions: the source, the audience, the variation map
1. **The source.**
- **A Lyra workflow** (built with our skills, or the user's own): `list_variations` and `get_workflow` on the original. Find every node by the layer it carries: the person (character, keyframes, phone shots, B-roll with hands, clips, talking head), the place and time (every image and clip prompt's environment line), props, voice (clip voice anchors, VO node), style. Read the prompts: they give the original world.
- **A finished video, the user's own ad** (a file or a public direct link): `create_upload` → `attach_upload`. Analyse it as in `lyra-copy-competitor-ad` Path 2 (frames every 3 s and at each cut, transcript with timestamps); only the production breakdown is needed: shots with times, person, wardrobe, place, props, light, camera setup, voice, speech, sound, UI moments, end card. It is the user's footage, so it may serve as an editing or motion reference (Best way to build it).
- **A concept not built yet** → build it with the matching skill and plan the versions from the start; this file gives the variation map.
Check `list_uploads` first.
2. **The original world card ("V1, control").** One note in the `lyra-ugc-video` format plus the world: **person** (age, look, hair, skin, energy, archetype) · **wardrobe** · **setting** (place, 2 to 3 lived-in details) · **props** (including any vehicle) · **time, season, light** · **market markers** · **voice** (anchor, language) · **polish and palette**. Every version is written against it, layer by layer.
3. **Brand Kit and audience** (base Reference I; several kits → ask which; never mix two). Read: segments and their daily life, pains in their words, desires, objections, markets and languages, positioning, must include / must exclude, forbidden claims. Reuse the pain map (`lyra-video-hooks` Step 1). No segments in the kit → 3 to 5 segment hypotheses from the app card, to confirm, and keep moving in the same message.
4. **Variation map** (user text node "Variation map"). One line per candidate: code · segment · mode A (the one layer) or B (the bundle) · what changes, layer by layer · hypothesis · why this segment matters. Offer 3 to 5, recommend 2 with one line why.
> V2 · students (same segment as V1) · A: person only (a converted skeptic, Leo, 22) · a doubting peer earns more trust than a tired one
> V3 · students · A: setting only (a shared dorm room instead of her own bedroom) · a cheaper, louder room is closer to most students' nights
> V4 · night-shift nurses (kit segment 2) · B: person, wardrobe (scrubs on the chair, mask marks), time (9 am, daylight through blinds), 4 words · nurses stop for someone who sleeps at the wrong time like them
> V5 · Brazil, students · B: person, setting, market markers, voice and language (Brazilian Portuguese) · a local face, room and voice beat a dubbed import
5. **Intake quiz** (base Step 1 format: one message, multiple choice, options from the Brand Kit, the recommended option first): which segments, markets or layers (with your recommendation) · mode A or B per version · how many (default 2 + the original as control) · language per version · screenshots, if a phone moment must be rebuilt and they aren't in the workflow · anything the brand doesn't want on screen (an age group, a car class, a look).
**Defaults (state, don't ask):** 2 versions + the original as control · **one variation per version**, copied from the original, which stays Main and untouched · mode A for tests, B for a new segment or market · cheapest informative layer first when the user has no preference (voice on a separate VO, a prop, wardrobe) · same length, ratio and platform as the original · real people: Seedance 2.5, references only, the original's resolution (720p by default), sound on · Nano Banana Pro for every image, 9:16, 2K (4K for close selfies) · captions changed only where words changed · same music, end card, CTA and hook.
**Recommended first run:** A. The changed images (portraits, wardrobe or world frames for every version; images are cheap, and they show whether the variation reads in one glance).
---
## Step 1a: casting and world-building from the audience
**Start from the segment's life, not from a label.** Write the situation first (a nurse after a night shift, a dad with a toddler, a freelancer between clients, a student in a shared dorm), then derive every layer from it: who they are, what they wear at the pain moment, where they are, what's around them, what time it is, how they sound.
**Person.** Casting follows `lyra-ugc-video` "Person" (archetypes, character card, realism):
- Markets look and sound local: a version for Brazil is a person from there, not the original person re-dressed.
- Respect, not stereotypes: no caricature of age, gender, ethnicity, body, religion or class; no accent played for a laugh; no costume of an identity. A persona is a specific person, not a demographic.
- Adults speak (18+); in kids and family apps the parent speaks. No real people, creators, celebrities, lookalikes or cloned voices.
**Wardrobe and styling.** What this person really wears at that moment (home clothes at 2 am are not an outfit). Occupation signals are accurate and generic: scrubs without a hospital name, a uniform without a real employer's logo. No visible brand logos on clothes, bags or shoes. Styling carries income and taste quietly (fabric, fit, wear), never as a joke.
**Setting and background.** The same situation, re-dressed for this life: lived-in, 2 to 3 specific details, light that is really there. Market-accurate interiors and streets. Never a showroom; never readable signage or text (blur or avoid it).
**Props and vehicles.** One hero prop per scene, chosen because this segment really has it (a stroller, a hospital lanyard without a name, a work laptop, a gym bag). Cars: the class and age signal the life (a used hatchback with a child seat, a company sedan, a delivery scooter); generic, no badges or plates, interior details instead of the logo; phone in a mount or the car parked. The phone's body may change (a generic modern phone of the kind this market uses), **the screen never does**.
**Time, season, light.** The pain moment's real time for this segment (a shift worker's "night" is 9 am); the season of the market at launch; wardrobe and light follow.
**Market markers.** Architecture, window views, sockets, food, interior style, street life, without text. Enough to feel local, not a postcard.
**Voice and language.** Rewrite the voice anchor for the person and the market; another language = the speech written in that language (not translated word for word), new captions.
**Words and the platform.** The person may talk about their own life in first person ("I'm on nights this week"). The ad never tells the viewer they have a personal attribute ("Are you over 50?", "Drowning in debt?"): Meta restricts ads that assert or imply personal attributes such as age, health, finances, religion, ethnicity or sexual orientation. Callouts by situation or habit ("Night owls, listen") are the safer form. Check current platform rules; this is not legal advice.
---
## Step 2 addition: the variation sheet
Before building, a user text node "Variation sheet", part of the concept the user approves:
1. **Lock list:** what stays identical in every version (message, beats and timing, camera setup, action, the phone screen, music, CTA, end card, hook, and in mode A every layer except the tested one).
2. **World cards:** V1 (control) and every version, the same eight layers, voice anchor included.
3. **Line audit** (mode B, or a new language): every spoken line and caption marked **universal** (stays) or **identity-bound** (adapts: a time, an occupation, a place name), with the new words. Same job, same length (about ±10% words), same claims. More than identity-bound words changing → it is the multiplier, say so.
| Beat | Time | V1 line | Bound? | V4 line | Words V1 / V4 |
|---|---|---|---|---|---|
| Hook | 0 to 3 s | "Two a.m. and my brain won't shut up." | yes (the time) | "Nine a.m. and I still can't sleep." | 8 / 7 |
| Old way | 3 to 6 s | "Tea, podcasts, counting sheep… nothing." | no | same | 5 / 5 |
4. **Side by side:**
| Layer | V1 (control) | V2 (A: person) | V3 (A: setting) | V4 (B: nurses) |
|---|---|---|---|---|
| Person | Mia, 21, student | Leo, 22, student, skeptic | Mia | Ana, 29, nurse |
| Wardrobe | grey hoodie | black hoodie | grey hoodie | navy t-shirt, scrubs on the chair |
| Setting | own bedroom | own bedroom | shared dorm room, roommate's bed in the background, string lights | own bedroom, small flat |
| Time, light | 2 am, phone light, lamp | same | same | 9 am, daylight through blinds |
| Voice | young woman, soft American, sleepy | young man, dry, flat | same as V1 | woman, late 20s, warm, low, tired |
| Words changed | — | none | none | hook (the time) |
| Hypothesis | — | a doubter earns more trust | a louder, cheaper room is closer to their nights | nurses stop for wrong-time sleep |
---
## Best way to build it
The user's explicit choices override any row. Models and prices: base Reference A.
| If the source is | Best approach (graph) | Models |
|---|---|---|
| **A Lyra workflow with a finished creative** (default) | **one variation per version** (below): `create_variation` copies the whole canvas with its results → `switch_variation` → `update_node` only on the nodes that carry the changed layers (layer map below) → rerun only those and what depends on them → Video Editor | as the original |
| The scene must stay exactly as in the original except the changed layer (strict mode A) | in the variation, a **frame swap** image node: the copied frame (still holding the original result) + the new element (portrait, outfit, car, room) → the clip takes the swapped frame instead of the old one | nano-banana-pro · as the original |
| A workflow on frame models (Seedance 2.0, Kling) | as the default; the new or swapped frame becomes the clip's first (and last) frame, linked right after it has a result and the user selected one | nano-banana-pro · seedance-2.0 / kling-v3-video |
| A version that needs its own workflow (another app or client, shared separately) | the workflow menu (⋮ next to the name) → **Save as a new workflow**; no MCP tool does this, so ask the user to click it (or do it in their browser if they allow), then work there as in the default row | as the original |
| **A finished video, the person speaks** | frames + transcript → the new portrait and world frames (frame swaps on the key frames) → **one Seedance 2.5 clip** with them as references, the speech in quotes (same or audited lines), the shot plan from the breakdown as "cut to" with lengths → optional: the original video as **[Video1], editing reference only**, when the timing must match closely (it can leak the old person or place: check) → Video Editor with the original's music, end card and UI inserts, if the user has the files | nano-banana-pro · seedance-2.5 |
| A finished video, no speech or a separate VO, the movement matters (a walk, a dance, a gesture) | new portrait + frame swap of the first frame → **Kling 3.0 Motion Control** with the original video as the motion source (the user's own footage only) → VO and music in the Video Editor | kling-v3-motion-control · elevenlabs/v3 |
| Voice or language only, with a separate VO | the cheapest version: a new VO node or voice (`list_voices`), the text in the new language if needed, new captions; no images or clips rerun | elevenlabs/v3 |
| Hands only (POV) | the hands are the person: skin tone, age of the hands, nails, rings, sleeves, watch; plus the surface and props under them; UI on screen → Seedance 2.0 frames | nano-banana-pro · seedance-2.0 |
| Car formats (car vlog, parked confession) | the car is a strong layer on its own: class, age, interior, what lies on the seat; swap it on the frames, keep the person and the mount | nano-banana-pro · seedance-2.5 |
| Two people | vary one or both, each with its own card and voice anchor; lines tied to [ImageN] | seedance-2.5 |
| A stylized character or mascot | a new original character, outfit or world in the same style family; the brand's own mascot is never replaced without the user's yes (it is brand identity) | nano-banana-pro · seedance-2.0 |
| A talking head node in the original | new face image and/or background + new voice audio | veed/fabric-1.0 |
| A new market | mode B: person, setting, market markers, voice and language; the speech written in that language; screenshots of the localized app for the phone moment | seedance-2.5 |
| Many versions, tight budget | the changed images for all; clips only for the 1 to 2 the user picks; cheapest layers first | nano-banana-pro · seedance-2.5 |
### Variations: the way to make a version
In Lyra every version of a finished creative is a **variation** of its workflow: the **Create variation** button above the canvas (the `create_variation` tool) duplicates the whole space (every node, prompt, connection and result) into a new version. The original stays **Main** and untouched as the control; the change is written into the copy.
**Make a variation when:** the Brand Kit has two or more audience segments (one variation per segment) · the user wants another language or market · a person, wardrobe, setting or prop test · a fatigued winner gets a new look · the user names a change ("same, but a man in his 40s", "same, but in a car"). One variation = one version (one layer in mode A, one bundle in mode B).
**Step by step:**
1. `list_variations` → find the original (the main one, unless the user names another). Rename it if needed: `rename_variation` "V1 · Mia · students (control)".
2. `create_variation` with `copy_from_variation_uuid` = the original and `title` = code, what changed, segment, language: "V4 · Ana · nurses · EN", "V3 · dorm room · students · EN". The copy carries the original's results, so everything that doesn't change is already there and never reruns.
3. `switch_variation` to it (Lyra renames the workflow after the main variation; tell the user which one is open), then `get_workflow`.
4. Write the change in with `update_node`, only on the nodes that carry the changed layers (layer map below). Everything else stays word for word. Another segment or market with its own kit → `assign_brand_kit` on this variation (each variation has its own).
5. Read the price on the nodes that will rerun and put it in the approval message (base Step 6: one question, then run everything). Unchanged nodes keep the copied results.
6. Repeat from step 2 for the next version (always copy from the original, not from another version).
7. When done, `switch_variation` back to the original if the user wants it shown first, and say which variation holds which version.
### The layer map: which nodes to update, what to rerun
| Layer changed | `update_node` on | Rerun |
|---|---|---|
| Person | the character node (new card, opening with "A different person from the original:"); the identity line in every image and clip that shows the person; the voice anchor | character → images with the person → clips → Video Editor |
| Wardrobe and styling | the outfit and styling in the character card; the same words in every image and clip prompt that names the outfit | character → images with the person → clips → Video Editor |
| Setting and background | the environment line in the character node (if it shows the place) and in every image and clip prompt | every image and clip that shows the place → Video Editor |
| Props and vehicles | the prompts of the scenes where the prop appears | those images and clips → Video Editor |
| Time, season, light | the light and time line everywhere; wardrobe if it follows | every image and clip of the scene → Video Editor |
| Market markers | the environment details everywhere they show | those images and clips → Video Editor |
| Voice and language | the voice anchor and the audited lines in clips with speech; or the VO node's voice and text | native speech: the clips with speech; separate VO: only the VO → Video Editor; captions in the editor |
| Polish and palette | the style line everywhere | almost everything |
After `update_node`, `get_workflow` on the variation and search every prompt for the old value (the old name, the old outfit, the old room): one forgotten node puts two worlds in one ad.
### The portrait: Lyra's Character Generation rules
When the person or the wardrobe changes, the new character follows the rules of Lyra's own **Character Generation** node, so it feels like a real person from Instagram Stories or TikTok. If the canvas has a Character Generation or Character Brief node (from a template), `update_node` its prompt (the tools can't create these nodes); otherwise the character is an Image Generation node (Nano Banana Pro) with a prompt written to the same rules:
- **Natural, not polished or "model-like"**; slightly imperfect: skin texture, asymmetry, natural posture.
- **Looks directly into the camera**: selfie or front-facing POV.
- **A believable real-life place tied to the product context** (the pain moment), not a staged production.
- **No text** in the image: no captions, no watermark; text is added in the Video Editor.
- **Matches the scene context**: pose, expression and framing fit the scene; the identity stays.
- **Framing by shot:** full body for lifestyle, action or environment (with footwear) · waist up for conversational, product-holding or testimonial · close-up for emotional hooks, reactions, hero frames.
- **Expression by the scene's mood:** excited or caught for a hook frame, thoughtful or tired for the problem, relieved or confident for the solution.
- **Framing by ratio:** 9:16 → the person in the central 65%, space for text top and bottom · 1:1 → waist up, centered · 4:5 → like 1:1 with a little more vertical space · 16:9 → full body or environment, off-center on the thirds.
- **The user's direction comes first** (scene, pose, expression, outfit, place).
### Frame swaps (when everything else must stay exactly)
Rerunning from the changed node down usually gives the same scene with the new element, because every other word of the prompts is unchanged. When the rest must stay exactly as in the original (strict mode A, or a finished video as the source), swap inside the frame itself:
- **Person swap** (keep the world, change the person): portrait first (by the rules above, count 2, the user picks), then one Image Generation node per key frame with the original frame (in a variation: the copied frame, before it is rerun) and the new portrait connected.
- **World swap** (keep the person, change the outfit, room, car, prop or light): one Image Generation node per key frame with the original frame connected, plus a reference image of the new element if there is one; the prompt keeps the person, pose, framing and phone exactly and changes only the named layer.
Check every swapped frame for **bleed** (traces of the old face, outfit, room or car), hands, the phone and the screen. Bleed → rerun with the "change only…" line moved to the start; still there after two tries → describe the scene in words and generate it fresh with the new element as the only reference for that layer.
### Voice
- **Native speech** (Seedance 2.5): rewrite the voice anchor for the person and market; keep the pace, so the timing holds.
- **Separate VO:** a new voice from `list_voices` (language, accent, gender, age, use case) with the same or audited text; check the real audio length (~1 s shorter than the video).
- **Exact words or a fixed brand voice:** VO as an audio reference in the Seedance 2.5 clip (base Reference C).
**Connections.** A variation copies the original's connections, so the graph already runs end to end. Only new nodes need links (base Step 4): a frame swap node → the clip instead of the old frame; a swapped frame on a frame model, right after it has a result. The "Variation map" and "Variation sheet" text nodes are notes for the user: they don't feed generation; consistency comes from the images connected as references plus the anchors written into every prompt.
**Layout and labels.** Each variation keeps the original's layout, Sections and order, so the user can flip between versions and see the same canvas. Put the "Variation map" and "Variation sheet" notes in the original's Sources Section before creating the variations, so every variation carries them. Relabel the nodes that changed with the version code: "V4 Ana: character", "V3: dorm room (frame)", "V4 Ana: clip", "Final: C1 · V4 nurses".
---
## Prompt rules (audience variations)
| Node | Write | Avoid |
|---|---|---|
| Variation map, variation sheet (text) | codes, segments, modes, layers changed, hypotheses, world cards, lock list, line audit, side by side | versions without a segment or a hypothesis; "a different vibe" without naming the layer |
| Portrait (character node) | "UGC phone photo" → "A different person from the original:" + the new card word for word → looking directly into the camera → a real place tied to the product context → framing by shot and ratio, expression by mood (Character Generation rules) → realism line → no text | details of the old card left in; "flawless", "editorial", model-like posing; a stereotype; text |
| Person swap (image edit) | each input's job first → keep list (room, light, angle, framing, pose, action, phone, objects) → replace only the person → mode B: other changed layers named → realism → no text | "the same woman, but older" (keeps the old face); re-describing the whole scene (it drifts) |
| World swap (image edit) | "[Image1] is the original frame: keep the person, face, hair, pose, the phone and the framing exactly" → change only the named layer, described concretely (class, age, materials, details) → realism → no text, no logos, no plates | changing two layers in a mode A swap; brand names, badges, readable signs |
| Clip | the original prompt; only the lines of the changed layers replaced (identity, wardrobe, environment, prop, light, voice anchor, audited lines); roles first | the old value left anywhere in the prompt; another camera, action or timing than the original |
| Clip with [Video1] (the user's own footage) | "[Video1] is an editing reference only: copy its cuts, shot lengths, camera movement and the person's actions. Do not copy the person's face, hair, body, clothing, the place or the voice; the person is [Image1]." | connecting it without a stated job; skipping the leak check |
| VO | the same text (mode A) or the audited text (mode B); a voice picked for the version | changing words in mode A; a voice that doesn't fit the face |
**Pattern: person swap (Nano Banana Pro, mode B).**
> UGC phone photo, same scene with a new person. [Image1] is the original frame: keep the bed, the duvet, the camera angle, the framing, her pose lying on her side and the phone held at arm's length exactly. [Image2] is the new person: use her face, hair, skin and build. Replace only the person in [Image1] with the woman from [Image2]: Ana, 29, warm olive skin, dark straight hair in a low messy ponytail, faint marks from a face mask on her cheeks, oversized navy t-shirt. The room changes only in light and two details: morning daylight through half-closed blinds instead of the lamp, light blue scrubs folded on the chair. Shot on a 24mm phone front camera, deep focus, natural skin texture, visible pores, slight dark circles, no beauty filter. No text, no captions, no watermark, no visible phone screen.
**Pattern: world swap, the car (Nano Banana Pro, mode A).**
> UGC phone photo, same person in a different car. [Image1] is the original frame: keep the woman, her face, hair, outfit, pose, expression, the phone in the dashboard mount, the framing and the camera angle exactly. Change only the car: a ten-year-old compact hatchback, worn grey fabric seats, a child seat visible in the back, a water bottle and a parking receipt in the door pocket, a scuffed plastic dashboard; daylight through the side window as before. Generic car, no logos, no badges, no readable text or plates. Phone-camera look, deep focus, natural skin texture. No captions, no watermark.
**Pattern: what changes in a clip prompt (Seedance 2.5).** Only the lines of the changed layers are replaced: the identity line ("[Image1] is Ana: her face, ponytail, navy t-shirt, and her bedroom in morning daylight"), the voice anchor ("Voice: woman, late 20s, warm low voice, neutral American accent, tired, unhurried") and the audited lines ("Nine a.m. and I still can't sleep."). Camera, action order, cuts, sound line, end state and the avoid line stay word for word. One fix is allowed: if someone speaks and the original's sound line lets music in, add "no music, no background music, no soundtrack, no score" (base Reference C); music stays the original's track in the Video Editor.
---
## Run options (audience variations)
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes, per option, multiplied by the number of versions. **A. Changed images (recommended):** portraits (count 2 per person), wardrobe or world frames · **B. Frame swaps and phone shots** for the picked images · **C. Clips and Video Editors** · or **D. Everything** at once (count 1; no pause to pick). Voice-only versions on a separate VO cost only the VO. When an image has several results, the user selects one in Lyra before the next stage (references pin to the selected result).
---
## Truth, casting and brand safety
- An AI person is a creative performance, never a real customer, user or reviewer (`lyra-ugc-video`, Truth and disclosure). Remind the user once to turn on the AI-generated label.
- **Claims stay identical across versions.** A new person, car or room never brings a new claim or result ("as a nurse I now sleep eight hours"); everything comes from the Brand Kit.
- No real people, creators, celebrities or lookalikes; no cloned voices.
- No stereotypes or caricatures of age, gender, ethnicity, body, religion or class; no accent or status as a joke; speaking persons are adults.
- No third-party brands: no logos on clothes, cars, laptops or mugs, no car badges or plates, no readable signs, no real employers on uniforms, no landmarks used as brands.
- No personal-attribute callouts to the viewer (Meta's personal attributes policy); the person speaks about their own life.
- Health, fitness and weight-loss apps: the person's body is never the result; no body before/after.
- **Brand safety** (Lyra's System Preamble, base Reference B): no profanity, no political statements, no unsubstantiated health claims, no competitor disparagement. The Brand Kit's **forbidden claims are enforced absolutely**, in every version's line, caption, visual and VO; if the user asks for one, say once that it is on the kit's forbidden list and leave it out unless the user confirms the kit is outdated.
---
## Deliverable and naming
1. "Variation map" and "Variation sheet" text nodes.
2. One variation per version (named with its code, what changed, segment and language), with the changed images, clips and its own Video Editor; the original untouched as Main, the control.
The original keeps its name as V1. Versions add `V{n}{Layer}{Segment}`, and the locale for a market version: `B6-A:CantSwitchOff-F:UGC-Storytime-C1H3-V2Person-Students`, `…-V3Setting-Students`, `…-V4Bundle-Nurses`, `…-V5Bundle-Students-BR-pt`. Node label: "Final: C1H3 · V4 nurses".
---
## Common mistakes (audience variations)
| Mistake | Prevention |
|---|---|
| Versions invented without reading the Brand Kit's audience | Variation map from the kit's segments; hypotheses to confirm when the kit has none |
| A version as a demographic label ("woman 35") | Start from the segment's life, derive every layer from it |
| Several layers changed in a "test" | Mode A: one layer; more is a mode B version, named as one |
| The message or angle changed "while we're at it" | Line audit; more than identity-bound words → the multiplier |
| The nurse still says "between lectures" | Line audit in mode B |
| A student in a premium car, a 55-year-old with a young voice | One-story test across all layers |
| A change too small to read (a shirt color) | The tested difference reads at thumbnail size in the first second |
| The original edited instead of a variation | Original untouched as Main, the control; `create_variation` per version |
| A variation copied from another version | Always copy from the original |
| Everything rerun, credits spent on unchanged nodes | Layer map: rerun only the nodes that carry the changed layer |
| One node left with the old person, outfit or room | `get_workflow` on the variation and search every prompt for the old value |
| Traces of the old face, room or car in a swapped frame | Portrait first; "change only…" at the start; bleed check |
| Portrait posed, glossy, looking away, or with text | Character Generation rules |
| Logos on the car, hoodie or laptop; readable signs | No third-party brands; generic objects, no text |
| The phone screen changed with the world | The screen is always the user's screenshot, identical in every version |
| A new version brings a new claim | Claims identical across versions, from the Brand Kit only |
| Stereotype, caricature, accent or status as a joke, a minor speaking | Casting and brand safety rules |
| "Are you over 40?" in the hook | First person about their own life; situation callouts only |
| A competitor's video used as the source | `lyra-copy-competitor-ad` |
## Quality gates (audience variations)
- **Stage 0 (variation map and sheet; Claude checks before sending):** every version tied to a segment from the Brand Kit (or a confirmed hypothesis) and a one-line hypothesis? Mode and layers named per version, one layer in mode A? World cards complete, voice anchors included? Lock list written? Line audit done for mode B and new languages, only identity-bound words changed, word counts within about ±10%, same claims? One-story test passed? No personal-attribute callouts, no brands, casting respectful?
- **Stage 1 (images):** the tested difference reads in one glance at thumbnail size? Everything else the same as the original (mode A)? The person and world read as the segment (mode B)? Portraits natural, imperfect, looking into the camera, no text? No bleed? Hands, phone and screen right (the screen identical to the screenshot)? No logos or readable text? Phone-real, not glossier than V1?
- **Stage 2 (clips):** voice fits the face, age and market? Lip-sync right, app name pronounced right? Beats and timing match the original (about ±0.5 s)? Same camera behaviour? Person and world stable through the cuts? If [Video1] was used: no trace of the old person or place?
- **Stage 3 (finals), side by side with the original:** only the intended differences visible? Captions match the new words? Same music, CTA and end card? 9:16, the original's resolution, planned length? Named with its V code? AI label reminder given?
## After the test
- Launch the control and the versions the same day, with the same setup and budget, so only the visible world differs.
- Read: hook rate first (the visible world decides the first second), then hold rate, CTR, cost per trial and payers. Then the age, gender and country breakdowns in Ads Manager: did each version pull the segment it was made for? A version that wins its segment but loses overall is still a result: a segment ad.
- The learning is the layer: person, wardrobe, setting, prop, time, market or voice. The next round pushes the winning layer further, combines winning layers into one audience version, or keeps the winning world and tests new hooks (`lyra-video-hooks`) or new angles (`lyra-ad-concept-multiplier`) in it. A winning person can become the campaign's recurring face.
- Save to the project's creative repository: version, layers changed, segment, hypothesis, result.
lyra-brand-kit29.1 KB
View saved version →
---
name: lyra-brand-kit
description: "Brand Kit skill for Lyra - builds a mobile app's Brand Kit from whatever the user sends (brand book, deck, PDF, notes, website, App Store / Google Play link, logo, screenshots, past ads, reviews), writes it in the team's Brand Kit standard, fills it into Lyra, creates the first workflow with the kit assigned and the brand assets on the canvas, and holds the rules every Lyra skill follows to read and use a Brand Kit (app card, pain map, field-by-field use, claims, conflicts, updates). Use for \"here's our brand kit\", \"fill the brand kit\", \"set up my brand in Lyra\", \"create a brand kit from our website / store page / deck\", \"onboard this app\", \"update the brand kit\", \"what's in our brand kit\", \"find the pains in the brand kit\", or before any ad when no kit exists yet. All other lyra skills read the Brand Kit by this file."
---
# lyra-brand-kit
Foundation skill. Two jobs:
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
1. **Set up a brand.** The user sends whatever they have about the app. Claude turns it into a complete Brand Kit in the team's standard, fills it into Lyra, creates the first workflow, assigns the kit to it and puts the brand's assets on the canvas. The user ends with a ready workspace: one kit, one starter workflow, and the first ideas for ads.
2. **Use a brand.** Every Lyra skill (video, UGC, hooks, short drama, UI motion, statics, carousels, competitor copies, variations, translation, resize) builds on the Brand Kit. This file is the one place that says how a kit is found, read, turned into an app card and a pain map, used field by field, kept true, and updated after tests. Base skills' Brand Kit references (`lyra-video-ad-generation` Reference I, `lyra-static-image-generation` Reference L) follow this file.
**Why it matters.** Generic ads come from missing product context. Lyra's nodes read the assigned kit to understand the brand's tone, value and audience ("Write as much as you can, in any format", says the Brand Kit page), and every skill takes its person, pain, words, feature, claims, offer, tone and colors from it. A thin kit gives thin ads in every skill; a wrong fact in the kit repeats in every ad.
**This is a way of thinking, not a script.** The rules are defaults and good practice; use judgment and say why in one line when you choose differently. Fixed: truth (nothing in the kit the sources don't support, no invented claims, numbers, reviews, prices or awards), the user's confirmation before a hypothesis becomes a fact, forbidden claims enforced absolutely, one kit per brand per ad (never mixed), Lyra's technical limits, and the user's explicit choices.
---
## The 6 steps (setup)
1. **Intake:** collect and read everything the user sent; research the store page and site if there's a link.
2. **Fact sheet:** sort what was found into facts, gaps and hypotheses; ask once for what only the user knows.
3. **Write the kit** in the Brand Kit standard (below), facts only, hypotheses marked.
4. **Approve:** the user sees the kit and the open questions, and says yes or corrects.
5. **Fill it into Lyra** (route by what this session can do) and check it with `list_brand_kits`.
6. **Starter workflow:** create it, assign the kit, upload the assets, add the Brand Kit notes, offer the first ads.
Steps 1 to 4 spend no credits. Step 6 spends none either: the starter workflow generates nothing.
---
## Step 1. Intake
**What the user may send, and what to take from it:**
| Source | Take |
|---|---|
| Brand book, style guide, one-page brand sheet (often an image), deck, PDF, Notion or Docs page | name, slogan, positioning, audience, tone of voice with examples, colors (hex), fonts, logo rules, do's and don'ts, legal lines |
| Product or marketing brief, notes typed in the chat | what the app does, who it's for, pains, features, offer, claims, markets |
| **App Store / Google Play link** | title, subtitle, category, description, feature list, screenshot captions, rating and number of ratings, price and trial, languages; the store promise the ads must match |
| **Reviews** (store, Trustpilot, Reddit, comments, support) | customer words in four kinds: **pain** (before the app), **outcome** (the relief), **objection** (why they hesitated), **discovery** (what surprised them); repeating patterns only |
| Website, landing page | positioning, headline promises, proof (press, partners, numbers), pricing, FAQ (objections) |
| Logo, app icon | the logo files (main, light, dark, white, black), the icon; colors measured from the pixels |
| App screenshots | the real UI: feature names as written in the app, key screens, UI colors |
| Past ads, winning creatives, performance notes | what already works (concepts, hooks, formats, segments), the tone actually used |
| Competitors named by the user | what the app does differently; claims every app in the category repeats (to avoid) |
| An existing Lyra kit (`list_brand_kits`) | the current text, colors and logo, to update instead of starting over |
**How to read:**
- Read **every** file fully. Look at every image yourself (logo, screenshots, ads). Files that exist only inside Lyra can't be seen: ask for them in the chat.
- A store link or website: open it if you can browse (web fetch or a browser); read the page, the description and the latest reviews. Can't browse → say so once and work from what was sent.
- **Colors:** take hex from the brand book when it gives them. Otherwise measure from the logo and screenshots (when you have the files and a shell: PIL, the most frequent non-white, non-black colors, then the accent), never guess from memory. Give each a role: primary, accent / CTA, background, text, secondary.
- **Fonts:** only names the brand book or the user gives. Otherwise describe the style (heavy geometric sans, rounded, serif) in the Visual identity section, without a font name.
- Several apps or brands in one pack → one kit per app; ask which first if unclear.
- A brand that exists in several markets with different offers or claims → one kit per market, or a market section in one kit; ask the user which they want (`lyra-image-translation` reads kits per market).
**Real brand or demo brand.** Ask (or read from the request) whether the brand is real or a fictional demo (for a webinar, a template, a test). Real → facts only, hypotheses marked and confirmed. Demo → Claude may invent everything, consistently, and writes "Demo brand: fictional, all details invented" as the first line of the description so no skill treats it as real proof.
## Step 2. Fact sheet and questions
Sort everything into three lists before writing:
- **Facts:** stated in a source; note the source next to each one ("store page", "brand book p. 4", "user").
- **Gaps:** a field of the standard nobody covered.
- **Hypotheses:** what Claude infers to fill a gap (a segment, a pain, an objection, a USP option, a trigger), written in the audience's words and marked **(hypothesis)**.
**Ask once, in one message, only what only the user knows** and what the ads can't do without. Propose hypotheses in the same message so work keeps moving:
1. Real brand or demo?
2. Who the app is for, if the sources disagree or say nothing; which segment matters most.
3. Approved claims and proof (ratings, numbers, awards, press, partners) and **forbidden claims** (health, finance, kids, "#1", "free", guaranteed results, competitors). Health, finance and kids apps: always ask.
4. The offer and CTA (free trial length, price, discount), per market if it differs.
5. Markets and languages.
6. Must include / must exclude (a disclaimer, a word the brand never uses, a mascot rule).
7. Is AI-generated content allowed, and is there a disclosure rule?
8. Missing files: the logo (vector or PNG on transparent), the app icon, 3 to 6 key screenshots (screenshots only, never a screen recording), product photos if physical, past winning ads.
**Defaults (state, don't ask):** the team standard below · the brand name exactly as on the store page · English (the kit's language follows the brand's main market or the user's choice) · colors from the logo and screenshots with roles · hypotheses marked until confirmed · the starter workflow named "{Brand} · Start".
## Step 3. The Brand Kit standard
Lyra's Brand Kit has these fields: **Brand Name**, **Website**, **Brand Description** (one free text field, Markdown works, "write as much as you can"), **Color Palette** (hex + label per color), **Main logo**, **Logo variations** (light, dark, white, black, custom), **Brand Assets** (reference files for the team and the generators).
Almost everything the skills need goes into **Brand Description**, written in this order with these exact headings (the team's existing kits use them, and every skill looks for them). Bold headings, short paragraphs, one fact per line; no fluff.
```
Category: {store category}
Demo brand: fictional, all details invented ← only for demo brands
**Slogan**
*{one line}*
**One-liner**
{App} helps {who} {do what / get what} by {how}.
**Marketing Description / Positioning**
What the app is and what it is not (vs the category). The core belief. The level: mass, premium, wellness, playful, expert. 4 to 6 sentences.
**Target Audience & Pain Points**
**{Segment 1 name}**
Who: age range, situation, daily life, where and when the problem shows up.
Main pain point: in their words; what they already tried and why it failed.
What they actually want: the outcome and the identity ("someone who…").
Objections: why they hesitate to install or pay.
Customer words: 2 to 4 short real phrases from reviews (only real ones).
(repeat for 2 to 4 segments)
**Psychological Triggers**
**{Trigger name}**
What it is and how an ad uses it, in 1 to 2 lines. (3 to 5 triggers)
**USP Options**
Option 1: … Option 2: … Option 3: …
**Key Features / Value Proposition**
**{Feature name exactly as in the app}**
What it does for the user, in one line. (4 to 6 features; mark the hero feature)
**Proof & Approved Claims**
Real ratings, number of ratings, downloads, users, awards, press, partners, studies, with the source. "None approved" if none.
**Forbidden Claims**
What ads must never say or show. Category rules (health: no diagnosis, no cure, no body before/after; finance: no guaranteed returns; kids: no child in distress). "None stated" if none, never left out.
**Offer & CTA**
Trial, price, discount per market; the CTA lines the brand uses.
**Tone of Voice**
3 to 5 adjectives; we are / we are not; 2 rewrites: off brand "…" → on brand "…".
**Visual Identity**
Colors with roles and hex; the usage ratio if known. Fonts (names only from the brand). Photo or illustration style, the look of the people, the polish level (raw UGC, elevated, stylized). Logo rules. Mascot, if the brand has one (never invent one).
**Markets & Languages**
Countries, store languages, ad languages; market-specific names or offers.
**Must Include / Must Exclude**
Disclaimers, mandatory phrases, words the brand never uses, topics to avoid, AI disclosure rule.
**Template Hooks** ← only when the brand gives its own hooks or proven ones exist
The brand's lines word for word; proven winners marked.
**Core Product Narrative**
How every ad tells the brand: the familiar moment → the turn → the after-state; the tone; what the proof is and what the point is. 4 to 6 sentences.
**Links**
Store links, website, socials.
```
**Writing rules:**
- **Facts only.** Every claim, number, rating, price, review line and award comes from a source or the user. A gap stays a gap ("None approved", "None stated") rather than a plausible guess.
- **Hypotheses** may sit in Target Audience, Psychological Triggers and USP Options, marked "(hypothesis)", until the user confirms them; confirmed → the mark is removed. Never in Proof, Forbidden Claims, Offer or Features.
- **Pains in the audience's words**, concrete moments, not categories ("snaps at her partner over nothing", not "stress").
- **Feature names exactly as in the app** (from the screenshots or store page): the skills put them on screen and in VO.
- **Length:** as much as is true. The existing team kits run about 5,000 to 9,000 characters. If the field rejects a long paste, shorten Customer words and Psychological Triggers first, never Forbidden Claims.
- The **Color Palette** field gets every brand color with a label (Primary, Accent / CTA, Background, Text, Secondary); the same hex codes and roles are repeated in Visual Identity, because skills read the text.
- **Logo and assets:** the main logo in Main logo; light / dark / white / black versions in Logo variations; the app icon, key screenshots, product photos, mascot sheets, the brand book PDF in Brand Assets.
## Step 4. Approve
Send the user, in one message:
1. The full Brand Description as it will be pasted (in the kit's language).
2. The palette (hex, role), the logo and asset files that will be uploaded.
3. **Open questions:** each hypothesis to confirm, each gap that matters, in one short list.
4. The plan for Step 5 and 6 in two lines.
Nothing is filled into Lyra before the user's yes, unless the user said "just do it": then fill it, and still list the hypotheses and gaps in the report.
## Step 5. Fill it into Lyra
**Lyra facts (Oct 2026).** The Lyra MCP tools can **list** brand kits (`list_brand_kits`: uuid, name, description, website, logo URL, palette), **assign** one to a workflow (`assign_brand_kit`, replaces any assigned one, on the workflow's main variation) and **unassign** it. They can't create or edit a kit yet. Check the tool list at the start of every build: when a create or update brand kit tool appears, it is Route 1 and this paragraph is out of date.
Pick the route by what the session can do:
| Route | When | How |
|---|---|---|
| **1. MCP tool** | a create / update brand kit tool is in the Lyra tools | create the kit with name, website, description, palette; upload the logo and assets as the tool asks; then check |
| **2. Browser** | Claude can drive a browser where the user is signed in to Lyra | fill the Brand Kit page (below) |
| **3. User pastes** | neither | give the user copy-ready blocks per field and short steps; the user fills and says "done"; then check |
**Route 2, the Brand Kit page** (lyra.splitmetrics.com → sidebar **Brand Kits**):
1. **Update, don't duplicate.** `list_brand_kits` with `search` = the brand name first. A kit exists → open it and edit, after the user's yes.
2. **Create brand kit** (top right) creates the kit **at once**, named after the workspace, and opens it; the page **autosaves** ("Saved" top right), there is no Save button. Click it **once**; a second click makes a second empty kit.
3. **Brand Name:** replace the default name first. **Website:** the site or store link.
4. **Brand Description** is a rich text editor (TipTap with a Markdown extension), not a plain textarea: form-fill tools fail on it, and typing Markdown character by character leaves literal asterisks. Set it in one go from the page: `document.querySelector('.tiptap').editor.commands.setContent(md, {contentType: 'markdown', emitUpdate: true})` with the approved Markdown as a template string (check it has no backticks or `${`), then click outside the editor, wait for "Saved", and read it back with `list_brand_kits`: Lyra stores it as Markdown (bold headings come back as `**Heading**`). No script access → paste the text by hand from the copy-ready block.
5. **Color Palette:** **Add color** adds a swatch at #000000 → select the hex text field (triple click), type the hex, Tab → click **Label**, type the role, Tab. Add all swatches first, then fill them in order. **Presets** offers ready palettes: not for real brands.
6. **Main logo** (one image), **Logo variations** (several images) and **Brand Assets** (any files, several) are file inputs: with a browser file-upload tool, upload straight into each input (no click on the box: that opens the system file picker). Brand Assets takes the brand book PDF, the brand sheet, screenshots, product photos, mascot sheets. Without such a tool, tell the user exactly which file goes in which box and wait.
7. Never delete a kit or a file in it; if something was created by mistake, tell the user which one and let them delete it (or reuse an empty kit created by mistake for this brand).
**Route 3, copy-ready blocks:** one block per field, in the order of the page (Brand Name · Website · Brand Description · colors as "hex · label" lines · which file goes to Main logo, Logo variations, Brand Assets), plus: "Lyra → Brand Kits → Create brand kit (once, it saves itself) → rename it → paste each block → Add color per line → upload the files". Ask the user to say "done" and the kit's name.
**Check (every route):** `list_brand_kits` with `search` = the name → the uuid; the name exact, the description complete (start and end match), the palette hex codes and labels, the logo URL present. A difference → fix it (Route 2) or tell the user exactly what to fix (Route 3).
## Step 6. The starter workflow
The first workflow is a ready canvas for every next skill. It generates nothing and spends no credits.
1. `create_workflow` titled "{Brand} · Start".
2. `assign_brand_kit` with the kit's uuid. Check the result shows the `brand_kit_uuid`.
3. **Assets on the canvas:** `list_uploads` first (the user may have uploaded them); otherwise `create_upload` (a public link, or the file posted with the upload descriptor), `complete_upload` with the returned file id, then `attach_upload` for each. Lyra media links (the kit's logo URL) don't work as `{url}` sources: they need a sign-in. If the shell can't reach the upload host (a proxy refuses it) but Claude drives a browser signed in to Lyra, post the file from the Lyra page itself: `fetch` the file (a Lyra media URL of the kit's logo or asset works there), build the FormData with every field of the descriptor, POST it with the descriptor's Authorization header, then `complete_upload`. No way to send it → `open_upload_widget`, or ask the user to drop the files on the canvas. Label each node: "Logo", "Logo · white", "App icon", "Screenshot 1 · {screen name}", "Product photo", "Past ad · {name}". Screenshots, logo and icon are what the image and video skills connect as references.
4. **Notes** (`create_user_text_node`, notes for the user and the next skills; they feed nothing yet):
- **"App card"**: the one-paragraph card every skill keeps (format in Using a Brand Kit).
- **"Pain map"**: per segment: pains in their words, desires, objections, the moment where the pain shows up, the feature that answers it; marked (hypothesis) where not confirmed.
- **"Open questions"**: gaps and hypotheses still waiting for the user, if any.
5. `create_frame_node` around the assets: "STEP 1 · Brand assets — your logo, icon and screenshots" (pink); around the notes: "NOTES · Brand Kit notes" (slate). STEP notes, colors and placement follow `lyra-workflow-layout`.
6. `get_workflow` to check: the kit assigned, every node present and labelled.
7. If the user has the workflow open in a browser while it's being edited through the tools, the canvas may not refresh: ask them to reload it, or reopen it for them when you drive the browser.
**Then offer the first ads** (no build without a yes): 3 to 4 ideas, one line each, each tied to a segment and a pain from the pain map and to the skill that would build it, one recommended:
- "UGC, {segment}, {pain moment} → `lyra-ugc-video`"
- "4 hooks on {pain} → `lyra-video-hooks`"
- "A static, {layout} on {feature} → `lyra-static-image-generation`"
- "Animate the {screen} screen → `lyra-ui-motion-video`"
- "A 90 s story, {hero} → `lyra-short-drama`"
- "Copy a competitor's ad you like → `lyra-copy-competitor-ad` / `-static`"
## Report
One short message: the kit's name and what it holds (segments, features, claims status, colors), the route used and anything the user still has to do (files to upload, a stray kit to delete), the starter workflow's name and what's on it, the open questions, and the first ad ideas.
---
## Using a Brand Kit (rules for every Lyra skill)
Every Lyra skill follows this section before any concept, script, prompt or plan. A skill's own Brand Kit table (what UGC or short drama takes from it) adds to this, never replaces it.
### 1. Find the kit
Source order:
1. The user's words in this chat (always win).
2. A Brand Kit sent in the chat (text, file, link).
3. The kit assigned to the workflow (`get_workflow` → `brand_kit_uuid`), then the workspace's kits (`list_brand_kits`).
4. **One** candidate → confirm in one line: "I'll make it for {kit name}, right?" **Several** → ask which, by name. **None** → offer to set one up with this skill (Steps 1 to 6), or ask for the essentials in one message: app name, what it does, audience, pains, the feature to show, approved claims, forbidden claims, offer, tone, colors (hex), logo, icon, screenshots.
5. Once chosen, `assign_brand_kit` on the workflow if it isn't assigned. **Never mix two kits** in one ad. One kit per market → the market's kit.
### 2. Read it fully, every time
The whole description, not the first lines: the segments, Forbidden Claims and Must Exclude are usually near the end. Also the palette and the logo. A kit read in an earlier session may have changed: read it again at the start of every build.
### 3. Keep an app card for the session
> App card: {App} · {what it does in 8 words} · for {main segment} · pain: {main pain} · may show: {2 to 3 features, real names} · claims: {approved, or "none approved"} · forbidden: {short list, or "none stated"} · offer: {…} · tone: {3 words} · colors: {hex primary / accent} · assets: {logo, icon, N screenshots} · source: Brand Kit "{name}"
### 4. Build the pain map
From Target Audience & Pain Points, per segment:
- **Audience:** who, the situation, the daily moments where the problem shows up.
- **Pains:** in their words; what they tried and why it failed.
- **Desires:** the outcome and the identity they want.
- **Objections:** why they hesitate.
- **Product truth:** the feature that answers each pain, the claims, the offer, proof, tone, must include / exclude, forbidden claims.
- **Motivation layers** (for angles): what they fear, what frustrates them, what they want.
Pains missing, vague or generic ("stress", "busy life") → write 3 to 5 **pain hypotheses** in the audience's words, ask the user to confirm, and keep working in the same message. With a store link: the review research (pain, outcome, objection, discovery words) sharpens the map. Reuse a pain map already made for this app (the "Pain map" note in the starter workflow, or an earlier round).
### 5. What each part of the kit is for
| Brand Kit part | Used for |
|---|---|
| Category, One-liner | the app card; which category guide a skill uses |
| Positioning (mass, premium, wellness, playful) | the polish level: raw UGC, elevated, stylized; the realism and finish of statics |
| Segments: who, daily life | the persona (age, look, market), the place and moment of the pain, casting for audience variations |
| Pains, customer words | hook lines, the "old way" beat, the speech, headlines, carousel card 1, the pain chain in a story |
| Desires, outcomes | the result beat, the after-state, the payoff, identity triggers |
| Objections | skeptic and honest-review formats, objection-first spines, FAQ cards |
| Psychological Triggers | the concept mechanism and the hook type |
| USP Options, Slogan | headline and end card lines, the value proposition in the brief |
| Key Features (exact names) | the one feature per ad, the demo beat, what is shown on screen, the turn in a story |
| Proof & Approved Claims | the **only** numbers, ratings, reviews, awards and results an ad may say or show |
| Forbidden Claims | hard rule for every line, caption, visual, VO, card and ad copy |
| Offer & CTA | the CTA line, the end card, the offer card; never a price or trial not listed here |
| Tone of Voice | word choice, humour, energy of every line and the persona's voice |
| Visual Identity, Color Palette | palette anchors in every prompt, CTA and type colors, the world of a story; UGC uses brand colors only as subtle accents |
| Logo, icon (Main logo, variations, assets) | end cards and statics, exactly as supplied, never redrawn |
| Screenshots (assets) | every phone screen and UI insert, identical word for word |
| Mascot | only when the kit has one; never invented |
| Markets & Languages | the persona's market, the spoken language and accent, which kit or section per market for translation |
| Must Include / Must Exclude | hard rules in every plan and prompt |
| Core Product Narrative | the arc of the ad and the place of the app and the proof in it |
### 6. Truth and brand safety
- **Claims only from the kit or the user:** no invented numbers, ratings, reviews, durations of use, results, prices, offers, awards or press. AI-generated people are never presented as real customers or real experts; testimonials only from real reviews.
- **Forbidden claims are enforced absolutely**, in every line, caption, visual, VO and ad copy, including words that only become a forbidden claim in translation. If the user asks for one: say once that it is on the kit's forbidden list and leave it out, unless the user confirms the kit is outdated (then offer to update the kit).
- Brand safety (Lyra's System Preamble): no profanity, no political statements, no unsubstantiated health claims, no competitor disparagement.
- A demo brand's invented facts stay inside its own ads and are never used as proof for a real brand.
### 7. Conflicts and gaps
- **The user's words win over the kit;** name the conflict in one line ("The kit says calm and ironic; you asked for loud and hype: going with yours").
- **Sources disagree** (the app's UI is blue, the kit's main color is violet) → say it and ask which wins; default: kit colors for backgrounds, type and CTA, the screens exactly as they are.
- **A gap** is filled by asking or by a marked hypothesis, never from a competitor's ad and never from imagination. No approved claim → no claim. No real review → no review card. No screenshots → no readable screen. No mascot → a person, an object or an original illustration.
### 8. Feed learnings back
After a test, what was learned belongs in the kit: a winning pain, segment, hook type or angle; a losing one; new customer words; a corrected fact. Offer the update in one line ("Add 'exam-week brain' as a proven pain for Students?"), and on a yes update the kit (Step 5 route) and the "Pain map" note. Never change a kit silently, never remove a forbidden claim without the user.
---
## Updating a kit
"Update the brand kit", new materials, a new market, a rebrand: `list_brand_kits` → read the current kit → show a short diff (what is added, changed, removed, with the source) → the user's yes → fill it in (Step 5 route) → check. A rebrand or a new market with different claims or offers → ask whether to edit this kit or make a new one; workflows already assigned keep the old kit until reassigned.
## Common mistakes
| Mistake | Prevention |
|---|---|
| A plausible number, rating or review written into the kit | Facts only, each with its source; "None approved" when nothing is |
| Hypotheses saved as facts | "(hypothesis)" until the user confirms; never in Proof, Forbidden Claims, Offer, Features |
| Forbidden Claims left out because nobody mentioned them | Always ask; "None stated" written explicitly; category rules added |
| Generic pains ("stress", "no time") | Concrete moments in the audience's words; review research |
| Feature names paraphrased | Exact names from the app's screens or store page |
| Colors guessed | Hex from the brand book or measured from the logo and screenshots, with roles |
| Two empty kits from two clicks on Create brand kit | Click once; rename first; check `list_brand_kits` |
| A new kit made while one already exists | Search by name first; update instead |
| Long description cut on paste, nobody noticed | Read it back; compare start and end |
| Description pasted with literal asterisks | Set it through the editor's Markdown command, never typed character by character |
| Starter workflow without the kit assigned | `assign_brand_kit`, then `get_workflow` to check |
| A skill wrote ads from the first lines of the kit | Read it fully every time; Forbidden Claims and Must Exclude are at the end |
| Two kits mixed in one ad | One kit per ad; ask which |
| A kit changed or a forbidden claim removed without asking | Diff and the user's yes, always |
## Quality gates
- **Stage 0 (before showing the kit):** every source read? Every fact with a source? Every heading of the standard present (gaps written as such)? Pains concrete, in the audience's words? Feature names exact? Proof, Forbidden Claims, Offer free of hypotheses? Colors with hex and roles? Real or demo stated?
- **Stage 1 (after filling):** `list_brand_kits` shows the exact name, the full description, every color with its label, the logo? No duplicate kit?
- **Stage 2 (starter workflow):** the kit assigned? Logo, icon, screenshots on the canvas and labelled? App card, Pain map, Open questions notes in place? Frames? First ad ideas offered, each tied to a pain and a skill?
lyra-carousel46.9 KB
View saved version →
---
name: lyra-carousel
description: "Carousel ads for mobile apps in Lyra, 2 to 10 cards that tell one consistent story (same person, world, palette, type and layout grid on every card), written as one carousel script and cut into cards by Lyra's Text Split node. Use for \"a carousel for my app\", \"5 cards that tell a story\", \"swipe ad\", \"step by step carousel\", \"feature carousel\", \"before / after carousel\", \"photo dump / slideshow\", \"TikTok photo carousel\", \"split this text into cards\", or a story, article or script to turn into cards. Core image rules come from lyra-static-image-generation."
---
# lyra-carousel
Image mini skill. Builds a carousel ad as **one story told in N cards**: a hook card that stops the scroll and makes people swipe, middle cards that each carry one idea, and a last card that closes with the CTA. Every card looks like it belongs to the same set (same person, same world, same palette, same type, same layout grid), and the text reads as one voice from card 1 to card N.
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
The story is written once, as one **carousel script**, and Lyra's **Text Split** node cuts it into one part per card. Each part is a complete card prompt that feeds its card's image node. One script = one source of truth: the user edits the story in one place, reruns the split and the cards follow.
**Base skill first.** Everything not written here follows `lyra-static-image-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, concept card and layout map, on-image text, realism, styles, models (Reference A), layout library (B), styles (C), realism toolkit (D), persona and consistency (E), edits (F), UI and logo (G), sizes and languages (H), errors (I), de-slop (J), Meta statics (K), Brand Kit (L). This file only adds what is specific to carousels and to the split pipeline. If the two disagree, the user wins, then this file, then the base skill.
**Other skills for their parts.**
- Card 1 is the hook of the carousel: the line checks, awareness levels, hook base and "Final test" of `lyra-video-hooks` apply to its picture and its line.
- A person across the cards: casting, place and the one-story test from `lyra-ugc-video`; the persona image rules from the base skill (Reference E).
- Real app screens on cards (steps, features, proof): UI fidelity from `lyra-ui-motion-video` (screenshots only, exactly as supplied, word by word check).
- A competitor's carousel as the reference: `lyra-copy-competitor-static` analyses it (one JSON per card + card list); this skill builds the new set.
- The same carousel for another segment or market: `lyra-audience-variations` (layers, one-story test); new angles on a winning carousel: `lyra-ad-concept-multiplier`; other sizes and languages: `lyra-adapt-image`; the carousel as a video: `lyra-video-ad-generation` or `lyra-ui-motion-video` (the cards become keyframes, the same script split into scenes).
**This is a way of thinking, not a script.** The rules are defaults and good practice; use judgment and say why in one line when you choose differently. Fixed: truth (no invented claims, reviews, numbers, UI or logos), the Brand Kit's facts, UI fidelity, Lyra's technical limits, the Text Split node's rules, and the user's explicit choices.
---
## How to think about a carousel
**What it is.** A swipeable set of 2 to 10 cards (Meta), up to 35 slides (TikTok photo mode), all in one ratio. The feed shows card 1 and a glimpse of card 2; everything else is earned by swipes. So a carousel is a **sequence of promises**: each card pays off the last one and gives a reason to see the next.
**Three jobs, in order.**
1. **Card 1 stops the scroll and opens a loop.** It must work alone (many people see only card 1), and it **teases, not completes**: a question, a number of steps, a "before", a pain moment, an unfinished story. A card 1 that tells the whole message gives no reason to swipe.
2. **Middle cards carry one idea each**: proof, mechanism, one step, one feature, one reason. Two ideas on one card lower the swipe rate.
3. **The last card closes.** It resolves the loop and asks for one action. No new information: it sees only a fraction of the people who saw card 1.
**How many cards.** Default **5** for a story (hook, pain or proof, mechanism, payoff, CTA). **3** when the idea is simple (hook, value, CTA: the "sweet spot" for installs). 6 to 7 for step by step or listicles that need it; past 8, drop off is steep. More cards are never a goal; every card must earn the next swipe.
**Story or showcase.** Decide this first, because it changes the build and the Meta setup:
| | **Story carousel** (default for this skill) | **Showcase carousel** |
|---|---|---|
| What it is | one arc, card order matters (hook → … → CTA) | independent cards, each a complete mini ad (a feature, a persona, a use case) |
| Card 1 | an open loop | the strongest single card |
| Consistency | one person, one world, one voice across cards | one visual system (palette, type, grid); people and scenes may differ |
| Meta setting | **"show best performing cards first" off**, order locked | the auto-ordering may stay on |
| Split | the script is the story | the script is a list of cards |
**Final test for every carousel:** would the right person stop at card 1, feel a reason to swipe, understand one idea per card, and reach the last card knowing what the app does for them and what to do next? And does the whole set look like one carousel at thumbnail size, not five different ads?
---
## Consistent storytelling: the Story Bible
Consistency in a carousel has two layers: **what the viewer sees** and **what the viewer reads**. Both are fixed once, in a Story Bible, before any card is written. The Story Bible lives in a user text node "Story Bible" (a note for the user, connected to nothing) and its anchors are **copied word for word into every card** of the script.
| Anchor | What is fixed | Example (fictional app Calmly) |
|---|---|---|
| **Narrator and voice** | who speaks (I / you / the app / a friend), tense, tone, word budget per card | first person, Mia speaking, present tense, short and honest, ≤ 12 words per card |
| **Character** | the character card from the base skill (Reference E): age, face, hair, skin, outfit, accessories | "Mia · 21 · student · light brown skin, freckles, dark curly hair in a loose bun · no makeup, slight dark circles · oversized grey hoodie, thin silver hoops" |
| **World** | the place, its 2 to 3 lived-in details, the time of day and its progression | her small dorm room: grey duvet, string lights, a charger cable on the nightstand; night at card 1, morning at card 5 |
| **Camera and light** | phone-real or camera-real, lens feel, the main light source and how it changes with time | phone-real, 24mm, deep focus; bedside lamp + phone glow at night, soft window daylight in the morning |
| **Palette** | hex codes from the design sources (the client's images and screenshots → Brand Kit → the option the client picked), each with its role and source | navy #1B1F3B backgrounds and text bands, violet #8B7CF6 accents and CTA, cream #F4F1EA type |
| **Type system** | headline style, body style, size feel, case, color, position; from the client's references, screenshots or the kit's fonts | headline: heavy rounded sans, cream, very large, left-aligned in the top band; body: regular rounded sans, small |
| **Layout grid** | the same zones on every card, at the same shares of the frame | top 22% text band · middle 63% scene · bottom 15% footer with the progress counter (the CTA button only on the last card) |
| **Continuity devices** | what tells the eye "this goes on" | a progress counter "1/5" bottom-left, a small arrow "→" bottom-right on cards 1 to 4, the string lights running across every card |
| **Device** | the phone and how the screen appears | a generic modern phone in a navy case, screen front-facing, the user's screenshots exactly as supplied |
**Rules for the anchors.**
- **Images over words.** The character comes from a persona image connected as a reference to every card with the person; the look of the set can come from the approved card 1, connected to cards 2 to N as a style reference with its job stated ("[Image2] is a style reference only: copy its palette, type style, light, grain and frame; not its text, not its pose"). Words alone never guarantee the same face.
- **Word for word.** The anchor lines are pasted identically into every card of the script, never paraphrased. Claude checks this with a diff before building.
- **What may change, card to card, is planned.** Time of day, the expression, the action, the camera distance, the screen shown: write it in the card ("allowed to change") so the change reads as story, not as drift.
- **One voice.** The narrator and the tense stay the same; a carousel that starts with "I" and ends with "Your…" breaks the story unless the switch is the payoff.
**Story devices that make people swipe:**
- **Open loop:** card 1 asks or shows something unfinished; the answer arrives later (never left open).
- **Numbered promise:** "3 things…", "5 steps…" with a counter; people swipe to finish the list.
- **Time arc:** 2 am → 7 am, day 1 → day 7, before → after, the change visible on the same person in the same place.
- **Cliffhanger per card:** each card ends on a small question the next one answers ("So I tried one thing." → next card).
- **Continuity across the edge:** a shape, a line or an object that runs off the right edge of a card and continues on the next (a string of lights, a desk, a road). It invites the swipe; build it with the panorama option (Best way to build it) or keep it to a simple band that repeats.
- **Payoff:** the last card closes the loop with the app as the reason, and the CTA.
---
## Story arcs for app carousels
A reference, not a menu. Each arc with its card roles (5 cards unless stated) and when it fits. The concept picks one and adapts it.
| Arc | Cards | Works for | Notes |
|---|---|---|---|
| **Hook → proof → mechanism → stack → CTA** (default) | 1 hook (claim or outcome, ≤ 8 words) · 2 proof (a real screen, a result) · 3 how it works (the feature) · 4 a second proof or three variants to pick from · 5 CTA with a fallback line (offer from the kit) | most apps, cold traffic | the proof is a real screen or a real number from the kit, never a fake review |
| **Problem → agitate → solution → result → CTA** | 1 the pain moment on the person · 2 why it keeps happening · 3 the app as the fix (real screen) · 4 the change, same person, same place · 5 CTA | problem aware audiences | the agitate card never shames the viewer |
| **POV story / time arc** | 1 "POV: 2 am, brain won't stop" · 2 what she tried · 3 she opens the app (real screen) · 4 the next morning · 5 CTA | sleep, habits, wellbeing, learning | one person, one place, time moves; strongest consistency test |
| **Step by step** (Nubank pattern) | 1 "Your card in 5 steps" · 2 to 5 one step each on a real screen, numbered · last CTA | fintech, onboarding-heavy apps, anything that feels hard to start | shows the process before the click; lowers the trust barrier |
| **Feature walkthrough / use cases** (Notion pattern) | 1 a pain or outcome hook (not a logo header) · 2 to 4 one use case each on a real screen · 5 "Start free" | multi-feature apps | every middle card can stand alone; replace a branded header card 1 with a real hook |
| **Problem / solution stack** (Linear pattern) | 1 headline · 2 to 3 pain vs fix side by side, same frame · 4 offer | apps replacing a habit or an old tool | never name or mock a competitor (brand safety) |
| **Before / after** | 1 before (the situation, not a body) · 2 to 3 the change · 4 after · 5 CTA | organising, finance, learning, home, productivity | no body before/after for health or weight-loss apps |
| **Listicle / reasons why** | 1 "3 reasons nurses switched…" · 2 to 4 one reason each · 5 CTA | feature-rich apps, considered decisions | reasons from the kit's features and approved claims only |
| **Myth vs fact** | 1 the myth · 2 why people believe it · 3 the fact (from the kit) · 4 what the app does about it · 5 CTA | education, health habits, finance | the fact is a real, approved claim, or a common-sense one |
| **Persona gallery** (showcase) | 1 "Who it's for" · 2 to 4 one segment each with its use · 5 CTA | apps with several clear segments | showcase: auto-ordering can stay on |
| **Photo dump / UGC deck** | 4 to 7 phone-real photos of one person's day, short captions in their voice, the app in one or two of them, CTA last | Gen Z, lifestyle, habits; TikTok photo mode | looks like a real person's post; never presented as a real user |
| **Chat story** | 1 the first message (the pain in the user's words) · 2 to 4 the conversation · 5 the answer and the CTA | coaching, learning, AI companions | stylised generic bubbles; a fictional chat is never shown as real |
| **Comic / illustrated story** | 4 to 6 panels with one character in the brand's style | brands with a mascot, kids and family, casual apps | the brand's own mascot or an original character, described fully |
---
## The split pipeline: one script → Text Split → cards
### What the Text Split node does
Lyra's **Text Split** node (action `text_split`, model `openai/gpt-5-structured`) receives a text and returns it as an array of parts. Its own system prompt, word for word in effect:
1. It must split into multiple parts, never one.
2. It splits at every major structural boundary: headings ("##"), scene breaks, chapter markers, dividers ("---").
3. Each part is a complete section; it never splits mid-sentence or mid-paragraph.
4. It **drops the dividers** ("---"); they are separators, not content.
5. It **copies the text exactly** into each part: no rewriting, summarising or adding.
6. At least 2 parts.
7. **A target part count written before the text** makes it aim for about that many parts, still respecting the boundaries.
Two consequences shape everything below: **whatever sits between two dividers becomes one card's prompt, exactly as written**, and **anything before the first card becomes its own part** (and shifts every card by one).
### Writing the carousel script for the splitter
The script is a user text node "Carousel script", written by Claude, connected to the Text Split node.
1. **The target count goes in the Text Split node, not in the script.** Rule 7 reads a count "provided before the text": when the canvas node has a field for it (a part count or a prompt), set it to N there. Don't write "Target: 5 parts" as the first line of the script: the splitter copies text exactly, so the line can end up inside card 1 and be printed on the image. The dividers already make N parts.
2. **The script is the cards only.** No title, no intro, no Story Bible section, no notes: they would become parts. The Story Bible lives in its own note node.
3. **Cards separated by a line with only `---`.** N cards = N − 1 dividers. No `---` and no `##` anywhere inside a card.
4. **No markdown headings on the cards.** A heading is copied into the part and the image model may print it ("Card 1", "Hook"). Each card starts with its format line instead: `Static app ad, carousel card 1 of 5, vertical 4:5, …`.
5. **Every card is a complete, self-contained image prompt** (base Prompt rules, static ad): format and ratio in words → each reference's job → the **anchor lines word for word** (character, world, camera and light, palette, type system, layout grid, continuity devices) → this card's role, moment and allowed changes → the layout top to bottom with every text in quotes → the screen "exactly as supplied" + its key texts, if any → "The only text in the image is …" → a short "Avoid …" line. 100 to 220 words per card.
6. **References are named the same way in every card** ([Image1] = the persona, [Image2] = the style reference, [Image3] = the screenshot of this card), and each card's image node gets the same inputs in the same order, so the names stay true.
7. **One paragraph per card** where possible (the splitter never cuts inside a paragraph; one paragraph per card makes a wrong cut impossible).
**Pattern: carousel script (fictional app Calmly, POV time arc, 5 cards; cards 2 to 4 shortened here with […] for space, written in full in a real script).**
```
Static app ad, carousel card 1 of 5, vertical 4:5, UGC phone-photo style. [Image1] is Mia: use her face, curly hair in a loose bun and grey hoodie exactly. Mia, 21, light brown skin, freckles, dark curly hair in a loose bun, no makeup, slight dark circles, oversized grey hoodie, thin silver hoops. Her small dorm room at night: rumpled grey duvet, warm string lights along the wall, a charger cable on the nightstand. Shot on a 24mm phone camera, deep focus, warm bedside lamp from the right, cool phone glow on her face, natural skin texture, visible pores. Moment: 2 am, she lies on her side wide awake, staring at the ceiling, phone face down on the duvet. Layout from top to bottom: top 22%: a navy #1B1F3B band with the headline "2 am. Brain won't stop." in a heavy rounded sans-serif, cream #F4F1EA, very large, left-aligned · middle 63%: Mia in bed, the string lights running off the right edge of the frame · bottom 15%: navy band, small cream counter "1/5" bottom-left and a small violet #8B7CF6 arrow "→" bottom-right. The only text in the image is the headline, "1/5" and the arrow. Avoid: beauty filter, studio lighting, extra text, logos.
---
Static app ad, carousel card 2 of 5, vertical 4:5, UGC phone-photo style. [Image1] is Mia: […same anchor lines word for word…] Moment: 2:40 am, she scrolls her phone in bed, eyes tired, the room the same. Layout from top to bottom: top 22%: navy band, headline "Scrolling made it worse." […] bottom 15%: counter "2/5", arrow "→". The only text in the image is the headline, "2/5" and the arrow. Avoid: […]
---
Static app ad, carousel card 3 of 5, […] [Image3] is the app screen. Moment: she opens the wind-down timer; the phone faces us, the screen displays [Image3] exactly as supplied […] visible on screen: "Tonight's plan", "5 min", "Start". Headline "So I tried 5 minutes of this." […] counter "3/5" […]
---
Static app ad, carousel card 4 of 5, […] Moment: 7 am, soft window daylight from the left, the lamp off, she stretches in bed, rested, a small smile. Headline "Asleep before the timer ended." […] counter "4/5" […]
---
Static app ad, carousel card 5 of 5, […] Moment: morning, she holds the phone toward us with the timer screen [Image3]. Layout: top 22%: headline "Your 5-minute wind-down." · middle: Mia and the phone · bottom 15%: a wide rounded violet #8B7CF6 button "Try it tonight" with cream text, centered, counter "5/5" small bottom-left, no arrow. The only text in the image is the headline, the button, "5/5" and the phone screen. Avoid: […]
```
**Check before building (Claude, Stage 0):** the script starts directly with card 1; count the dividers (N − 1); no `##`, no title, no notes in the script; the anchor lines identical in every card (diff them); every card ends with "The only text in the image is …"; every quoted text matches the concept; total length of each card 100 to 220 words.
### Connecting it in Lyra
`Carousel script` (user text) → `Text Split` (`text_split`, `openai/gpt-5-structured`) → `Card 1` … `Card N` (Image Generation, Nano Banana Pro). The persona, the style reference and the uploads (screenshots, logo) connect to the cards that use them, in the same order on every card.
**What the MCP tools can and can't do (Oct 2026).** `list_node_configs` lists `text_split` with `openai/gpt-5-structured` as its preferred model, but there is **no create tool for it** (as with Creative Analysis). So:
1. `get_workflow`: a Text Split node already on the canvas (the user added it, or a template has it) → `update_node` its model and settings if needed, `connect_nodes` script → split → cards, read its price next to Run.
2. No Text Split node → ask the user once to add one from Lyra's node menu (one click on the canvas), then continue. Don't wait in silence: build everything else meanwhile.
3. **How the parts reach the cards must be checked on the first build** (which part goes to which image node, whether a connected text replaces or joins the image node's own prompt). Until the team has confirmed it, every card's image node **also gets its full card prompt in its own prompt field** (the same text as its part), so the carousel runs correctly either way. Write down what the first run shows in the project notes, so the next build skips this check.
4. Connect the split's outputs to the cards **in card order**, left to right on the canvas.
**Two modes, said in the plan:**
- **A. Split driven (recommended once confirmed):** the script is the source; the user edits the story in "Carousel script", reruns the split, reruns the cards. Best for iterating the story, changing N, testing new hook cards.
- **B. Direct (fallback):** the script stays as a note; each card's prompt lives in its image node. Use when no Text Split node is available or the routing isn't confirmed yet.
### The user's own text as the source
The split also turns **text the user already has** into a carousel: a blog post, a video script, a list of features, real reviews from the Brand Kit, a story, a lesson. Claude:
1. reads it and finds the arc in it (the hook, the beats, the payoff), proposes N cards and the arc in plain words;
2. restructures it into cards: the user's own words stay where they are the on-image text (the base rule: the user's words stay as given), shortened only with the user's yes; the anchors and the layout are added around them;
3. writes it as a carousel script (rules above), never feeding the raw text to the splitter: raw text would be cut at its own paragraph breaks and give cards without anchors, layout or the "only text" line.
---
## Step 1 additions: the carousel brief
**Ask first, build later.** Before any concept, Claude asks the client everything only they can give, in one message, and waits for the answers. Nothing about the look is decided before this. Ask for:
1. **The app:** name, store link, what it does, who it's for (or the Brand Kit, which covers it).
2. **The Brand Kit:** which kit (or `list_brand_kits` and confirm the one in the workspace), or the brand basics if there is none: colors (hex), fonts, tone, logo, icon.
3. **App screenshots:** the screens the carousel may show, current version, full resolution (screenshots only, never a screen recording).
4. **Style and design references:** images the client wants it to look like: their own past ads, brand photos, a mood board, a design system, a carousel they like. And in words: what style they want (photo, illustration, typographic, UGC, premium), and what they don't want.
5. **The story or the idea**, if they have one (or their text to turn into cards).
6. **Where it runs:** Meta Feed · Stories · TikTok photo mode; the language.
If the client answers only part of it, ask once more only for what's still missing; never re-ask what they said.
### Design sources: where the look and the colors come from
The look of the carousel (palette, type, style, graphic elements) is taken from what the client gives, in this order:
| Order | Source | What we take from it |
|---|---|---|
| 1 | **The client's words in this chat** | any explicit choice (a color, a style, "no illustrations") wins over everything below |
| 2 | **Reference images the client sent** (their own ads, brand photos, mood board, design system) | style, palette, type feel, composition, graphic elements, polish level |
| 3 | **The app's screenshots** | the app's real palette, type style, corner radius, icon and button style, so the cards match the app people will open |
| 4 | **The Brand Kit** | hex colors, fonts, tone, logo, icon; also fills everything the images don't show |
| 5 | **Nothing sent** | Claude proposes **2 to 3 style and palette options** that fit the audience and the category, one recommended; the client picks; never decided silently |
**How to read the images.**
- Claude looks at every reference and screenshot itself (attached in the chat or staged from a connected folder). Files that exist only inside Lyra can't be seen by Claude: ask the client to also send them in the chat, or work from the Brand Kit for that part.
- **Colors as hex from the pixels**, not by eye: a short script (downscale, k-means with 3 to 5 clusters, sort by pixel count, drop near duplicates), 2 to 4 colors with their role (background, text, accent, CTA).
- **Type:** describe the style (heavy geometric sans, rounded, serif, handwritten), weight, case; the font name only from the Brand Kit.
- **Style:** name it in the base skill's words (phone-real, lifestyle, typographic, flat vector, 3D…) and write what makes it that style.
- Write the result into the Story Bible (palette, type, style, layout grid) with its source next to each line ("violet #8B7CF6, source: Brand Kit; card background #F4F1EA, source: screenshot 2").
**Conflicts.** The images and the Brand Kit disagree (the app's UI is blue, the kit's main color is violet) → say it in one line and ask which wins. Default if the client doesn't care: brand colors from the kit for backgrounds, type and CTA; the screens exactly as they are.
**Whose images can feed generation.** The client's own images (their ads, their photos, their design system) may be connected to the card nodes as a **style reference with its job stated** ("[Image4] is a style reference only: copy its palette, light, type feel and grain; not its people, objects or text"). A competitor's or a third-party image is **analysis only**: never connected to generation (see `lyra-copy-competitor-static`). Unknown source → treat it as third-party and ask.
**Defaults (state, don't ask; only what the client didn't answer):** a **story carousel** · **5 cards** (3 when the idea is simple) · **4:5** (1080×1350) for Meta Feed, the same ratio on every card; **9:16** (1080×1920) for Stories and TikTok photo mode; 1:1 only when asked · English · style and palette from the design sources above (phone-real photo only when nothing points elsewhere and the client picked it from the options) · **Nano Banana Pro**, 2K (4K for a card with a readable screen or small text) · count 1 per card (2 for card 1 and the persona) · one persona connected to every card with the person · card 1 approved first, then connected as a style reference to the other cards · split driven when a Text Split node is available, direct otherwise · progress counter on, CTA only on the last card.
**Recommended first run:** A. Anchor first (Run options below).
## Step 2 addition: the carousel concept
Part of the concept the user approves, readable in a minute:
1. **Concept card** (base format) for the whole set: hypothesis in one line (why this story should work for this audience), the arc, story or showcase, N, ratio, style, palette.
2. **Story Bible** in short: narrator and voice, character card, world and time arc, camera and light, palette, type, layout grid, continuity devices.
3. **Card list**, one line per card: # · role · moment (what we see) · on-image text in quotes (with its word count) · screen, if any · what changes from the previous card.
> 1 · hook · Mia awake at 2 am, phone face down · "2 am. Brain won't stop." (5) · — · —
> 2 · pain · 2:40 am, scrolling, tired · "Scrolling made it worse." (4) · — · phone up, later time
> 3 · fix · opens the wind-down timer · "So I tried 5 minutes of this." (7) · timer screen · the screen appears
> 4 · result · 7 am, daylight, rested · "Asleep before the timer ended." (5) · — · morning light, smile
> 5 · CTA · holds the timer to camera · "Your 5-minute wind-down." + button "Try it tonight" (4 + 3) · timer screen · button appears
4. **The swipe test**, one line: what makes people go from card 1 to card 2 (the open loop), and how the last card closes it.
5. **The plan table** (base Step 2) and the model question.
The full carousel script is written after approval, at build time (Step 4), from this card list. Card 1 gets the most care: it is the hook, the thumbnail and the only card many people see.
**Text budget per card:** card 1 headline ≤ 8 words (it's a hook: one idea, the audience's words); middle cards ≤ 12 words in total; the last card a headline + a CTA of 1 to 4 words; at most 2 text blocks per card besides the counter. The ad's primary text (outside the image, ~125 characters before "more") and the per-card headline field (≤ ~40 characters) are written too, in the concept, and handed to the media buyer.
---
## Best way to build it
The user's explicit choices override any row. Models and prices: base Reference A.
| If the carousel has | Graph | Models |
|---|---|---|
| **A person across the cards (default story)** | Story Bible (note) · Carousel script → Text Split → Card 1 … N · persona node first (count 2, the user picks) connected as reference to every card with the person · card 1 run and approved first, then connected to cards 2 to N as a style reference | nano-banana-pro |
| No person (typographic, product, illustrated) | the same, without the persona; card 1 is the style anchor for the others | nano-banana-pro (Ideogram 3.0 Quality as a test for type-only cards that keep failing) |
| The client's own style references (their ads, photos, design system) | upload them (`list_uploads` first) → connect as a style reference to every card, job stated first; palette and type from them written into the anchors | nano-banana-pro |
| Real app screens (steps, features, proof) | one screenshot upload per screen card, connected only to its card; the screen "exactly as supplied" + key texts in the card; a separate phone-shot node when a screen keeps failing (base Reference G) | nano-banana-pro, 4K for screen cards |
| Showcase (independent cards) | the same graph; the visual system (palette, type, grid) as anchors, people and scenes may differ; no style reference from card 1 when the scenes must differ | nano-banana-pro |
| A continuous scene across cards (panorama) | **option 1 (safer):** a repeating band or object at the same height on every card, so the cards line up when swiped · **option 2:** one wide image (21:9) of the whole scene, cut into cards by the user's designer in Figma (Claude can't open Lyra results to cut them) · **option 3 (risky):** each next card with the previous card connected as reference, "continue the scene from the right edge of [Image2]"; check the seams | nano-banana-pro |
| The user's own text (article, script, reviews) | Claude restructures it into a carousel script → Text Split → cards | nano-banana-pro |
| A competitor's carousel as the reference | `lyra-copy-competitor-static` teardown (one JSON per card, card list) → the arc and roles kept, our story and look → this skill's build | nano-banana-pro |
| 9:16 for Stories / TikTok | a separate set at 9:16, **recomposed** card by card (keep top ~14% and bottom ~20% free), never cropped from 4:5 | nano-banana-pro (or `lyra-adapt-image` for simple layouts) |
| Many directions / tight budget | drafts of card 1 only on nano-banana-2 at 1K, count 2 to 3 → the user picks the direction → the full set on Pro | nano-banana-2 → nano-banana-pro |
| A video version of the carousel | the approved cards as keyframes, the same script split into scenes → `lyra-video-ad-generation` (people) or `lyra-ui-motion-video` (UI-led) | seedance-2.5 / 2.0 |
**Plan example** (base Step 2 table, Calmly, POV time arc, 5 cards):
| # | Node label | Node · model · key settings | Inputs (role) | Stage |
|---|---|---|---|---|
| 1 | Concept card + card list | user text (note) | — | — |
| 2 | Story Bible | user text (note) | — | — |
| 3 | Carousel script (5 cards) | user text | — | — |
| 4 | Text Split · 5 parts | text · text_split · openai/gpt-5-structured | 3 | 1 |
| 5 | Persona: Mia | image · nano-banana-pro · 4:5 · 2K · count 2 | — | 1 |
| 6 | Screenshot: timer | upload image | — | 1 |
| 7 | Card 1: hook · 2 am · 4:5 | image · nano-banana-pro · 4:5 · 2K · count 2 | 4 (part 1), 5 (person) | 2 |
| 8 | Card 2: pain · scrolling · 4:5 | image · nano-banana-pro · 4:5 · 2K | 4 (part 2), 5, 7 (style) | 3 |
| 9 | Card 3: fix · timer · 4:5 | image · nano-banana-pro · 4:5 · 4K | 4 (part 3), 5, 7, 6 (screen) | 3 |
| 10 | Card 4: result · morning · 4:5 | image · nano-banana-pro · 4:5 · 2K | 4 (part 4), 5, 7 | 3 |
| 11 | Card 5: CTA · 4:5 | image · nano-banana-pro · 4:5 · 4K | 4 (part 5), 5, 7, 6 | 3 |
Stages for a carousel: **1** = sources (split, persona, uploads) · **2** = card 1, the anchor · **3** = cards 2 to N · **4** = sizes, languages, variants.
**Canvas layout.** Section "Story" (concept card, Story Bible, Carousel script, Text Split) → Section "Sources" (persona, uploads next to the cards they feed) → Section "Cards" with the cards **in one row, left to right in card order**, so the user reads the carousel on the canvas like the feed shows it → Section "Sizes and languages". Labels: "Card 3: fix · timer · 4:5", never "Image 3".
## Run options (carousel)
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes, per option:
| Option | Runs | Results | Credits | Time |
|---|---|---|---|---|
| **A. Anchor first (recommended)** | Text Split + persona + card 1 (count 2) | the parts, 2 personas, 2 hook cards: the user picks the person and the look | {x} | ~1 to 2 min |
| B. Whole set | split → persona → all cards (count 1) | N cards | {x} | ~3 to 5 min |
| C. Drafts of card 1 | card 1 on nano-banana-2, 1K, count 3 | 3 directions for the hook card | {x} | ~30 s |
- Recommend A: the person and the look of card 1 decide the whole set; spending on cards 2 to N before they are right wastes credits.
- After A, the next pick is "cards 2 to N", with its credits, once the user has selected the persona and card 1 in Lyra (the references use the selected result).
- B has no pause to pick: keep count 1 everywhere; the style reference then comes from card 1's only result.
---
## Prompt rules (carousel)
| Node | Write | Avoid |
|---|---|---|
| Concept card (text) | the base concept card for the set + arc, story or showcase, N, the card list, the swipe test, primary text and per-card headlines | prompts meant for the model |
| Story Bible (text, note) | narrator and voice, character card, world and time arc, camera and light, palette (hex), type, layout grid, continuity devices, device | anything only in words that must be identical in images (that's what the persona and style references are for) |
| Carousel script (text → split) | N complete card prompts separated by `---`, anchors word for word in each, one paragraph per card | a title, an intro, notes, `##` headings, `---` inside a card, "same as card 1", references to the chat |
| Text Split | its own model and system prompt; the target count N in its own field, when the node has one | rewriting its rules; the count written inside the script |
| Card (image) | format line "carousel card k of N" → each reference's job → anchors word for word → this card's moment and allowed changes → layout top to bottom with every text in quotes → screen exactly as supplied → "The only text in the image is …" → "Avoid …" | a different palette, type, grid or narrator; "like the previous card"; more than one idea; a CTA button before the last card (unless showcase) |
| Persona (image) | base persona rules (Reference E), in the story's world, no text | a model look, a real person or lookalike |
| Edit of one card | base edit pattern: verb first, keep list, one change | regenerating the whole set for one card's fix |
**The 6 rules that matter most here:** (1) card 1 works alone and opens a loop; (2) one idea per card, the last card closes with one CTA; (3) the Story Bible's anchors word for word in every card, and the persona (and card 1) connected as references; (4) the script is cards only, separated by `---`, each a complete prompt; (5) the same layout grid and type on every card, counter and arrow as continuity; (6) every letter and every screen checked with the user, card by card, before anything is built on them.
---
## Truth and brand safety
The base skill's Truth and disclosure applies to every card. In addition:
- **Steps and features only as the app really works.** A step-by-step carousel shows the real order of the real screens; never a step the app doesn't have, never a screen redrawn.
- **The story is a creative scene.** Mia is an AI persona, never presented as a real user; a photo dump or a chat story never claims to be a real person's post or conversation.
- **Results and time claims** ("asleep before the timer ended", "fluent in 30 days") only when they are an honest, ordinary description of the scene and don't read as a promised result, or when the Brand Kit approves the claim. When in doubt, move the line to a feeling ("finally calm") rather than a result.
- **Comparisons** (problem / solution stack, old way vs app) never name, show or mock a competitor; no competitor UI.
- The Brand Kit's **forbidden claims are enforced absolutely** on every card, in the primary text and in the per-card headlines.
- Remind the user once, in the final report, about the platform's AI label for photoreal synthetic people.
## Deliverable and naming
1. Section "Story": concept card with the card list, Story Bible, Carousel script, Text Split.
2. Sources: persona, uploads. Cards in one row, in order. Sizes and languages.
3. The ad copy for the media buyer: primary text, per-card headlines, the CTA button, "order locked" (story) or "auto-order allowed" (showcase).
Names: `B{batch}-A:{angle}-F:Carousel-{arc}-C{concept}-Card{n}-{ratio}` (+ `-{lang}`, `-V{n}{what changed}`), e.g. `B6-A:2amBrain-F:Carousel-POV-C1-Card3-4x5`. The whole set shares the code up to `Card{n}`, so the media buyer uploads it as one carousel.
## Meta and TikTok setup notes (for the media buyer)
- Meta: 2 to 10 cards, all one ratio; 4:5 (1080×1350) or 1:1 (1080×1080) for Feed, 9:16 (1080×1920) for Stories with ~250 px clear at the top and bottom. Primary text truncates around 125 characters on Instagram, ~80 on Facebook; card headline ~40 characters; description ~18 to 30 characters (Facebook only). Keep key text inside the central 80%.
- **Story carousels: turn off "automatically show the best performing cards first"**, so the order stays. Showcase carousels can keep it on.
- The same CTA button on every card; vary the per-card headline so each card gives a reason.
- TikTok photo mode: up to 35 slides, 5 to 7 is the usual sweet spot, 9:16.
- Specs change: check Meta's and TikTok's current guides before export.
---
## Common mistakes (carousel)
| Mistake | Prevention |
|---|---|
| Card 1 tells the whole story, nobody swipes | Card 1 teases (question, steps, before, pain); the payoff comes later |
| Card 1 is a logo or a branded header | A real hook in the audience's words, with the `lyra-video-hooks` line checks |
| Two ideas on one card | One idea per card; the second idea is the next card |
| New information or a second offer on the last card | The last card closes the loop and asks for one action |
| Face, outfit or room changes between cards | Persona connected to every card; anchors word for word; card 1 as style reference |
| Palette, type or layout grid drift | The same anchor lines in every card; diff before building |
| Story Bible or a title placed in the script, the split shifts every card by one | Script = cards only; the Bible lives in its own note |
| `##` headings in the script, "Card 1" printed on the image | No headings; each card starts with its format line; "the only text is…" |
| A `---` inside a card, or a missing one | Count dividers = N − 1; one paragraph per card |
| Raw user text fed straight into the split | Restructure it into card prompts with anchors and layout first |
| Claims the split routing works before it was checked | Prompts also in each card node until the first build confirms it |
| A CTA button on every card of a story | Counter and arrow on cards 1 to N−1; the button only on the last card |
| 4:5 cards cropped to 9:16 | Recompose each card for 9:16 |
| Steps or screens the app doesn't have | Real screens only, in the real order |
| Concept written before asking for the kit, screenshots and style | Ask first (Step 1), one message, wait for the answers |
| Colors guessed by eye or picked by Claude while the client sent images | Design sources in order; hex measured from the pixels; source written next to each color |
| A style chosen silently when nothing was sent | 2 to 3 options, the client picks |
| A competitor's or unknown image connected as a style reference | Only the client's own images feed generation; others are analysis only |
| Auto card ordering left on for a story | Tell the media buyer: order locked |
| Ten cards "because Meta allows it" | 3 to 5 for installs; every card must earn the next swipe |
## Quality gates (carousel)
Claude can't see the results, so after each stage it sends the stage checklist and asks the user what works and what doesn't.
- **Stage 0 (concept and script, Claude checks before sending and before building):** the client was asked for the Brand Kit, screenshots, style references and the story before the concept? Palette, type and style traced to a design source (client's images, screenshots, kit, or an option the client picked), hex measured from pixels? Only the client's own images connected as style references? Arc named, story or showcase decided, N justified? Card 1 standalone, teasing, ≤ 8 words, passes the hook line checks? One idea per card? The last card closes the loop, one CTA, no new info? Text budgets kept? Every claim, number, offer and screen traced to the Brand Kit or the user? Script: cards only, target N set on the split node if it has the field, N − 1 dividers, no headings, anchors identical (diff), each card a complete prompt ending with "The only text in the image is …"?
- **Stage 1 (split, persona, uploads):** the split returned exactly N parts? Each part starts with its format line "carousel card k of N" and is complete (nothing cut, nothing merged)? Persona: a real-looking person in the story's world? Screens identical to the screenshots?
- **Stage 2 (card 1):** stops the scroll at phone size? Makes you want card 2? Every letter right? The look is the one the whole set should have?
- **Stage 3 (cards 2 to N), seen side by side in one row:** same person, outfit, room (except the planned changes)? Same palette, type, grid, counter and arrow on every card? The story reads when swiping, one idea per card, the time arc visible? Every letter, number and screen right? The last card's CTA clear and inside the safe zone? Looks like one carousel at thumbnail size?
- **Stage 4 (sizes, languages, variants):** 9:16 recomposed, nothing cut; texts re-checked in every language; variants change only the intended card or layer; names with codes; AI label reminder given.
## After the test
Read the carousel by the goal's cost per result (trial, payer), not CTR alone, and by its card-level drop off when the platform shows it: a big drop after card 1 → the hook card; after card 2 → the proof is weak; people swipe to the end but don't install → the last card or the offer. Refresh by **replacing the weakest card** (often every 10 to 14 days), not the whole set. Then offer 2 to 4 next steps, each with what changes, what stays and its credits:
- **Hook card test:** 2 to 3 new card 1s, cards 2 to N held constant (only the first part of the script changes; rerun split and card 1).
- **Audience version:** the same story for another segment from the kit (`lyra-audience-variations`: persona, wardrobe, world; the one-story test).
- **New angle:** the same arc with another reason to care (`lyra-ad-concept-multiplier`).
- **Languages and sizes:** `lyra-adapt-image` per card (Image Translation only on cards without UI; cards with UI get the localized screenshots and texts written in that language).
- **Video version:** the cards as keyframes, the script split into scenes (`lyra-video-ad-generation`, `lyra-ui-motion-video`).
Variants live next to the original in the same workflow (one row per version) or in a Lyra variation (`create_variation`, the original stays Main as the control). Save the arc, the card list and the result to the project, so the next carousel starts from what the team learned.
---
## Reference: what the research says (Oct 2026)
**Three documented carousels from app and software brands** (from adlibrary.com's 2026 teardowns; all observed running 60+ days, which signals a working ad but is not proof of performance; public libraries don't show reach or results for commercial ads, so "most popular" can't be measured from the outside):
1. **Nubank (fintech app), step by step, 5 cards, Meta, Brazil and Mexico.** Card 1 announces five steps; the next cards walk through download, form, selfie check, card delivery and first purchase as phone screens. Works because it shows the whole process before the click and lowers the trust barrier of a high-commitment product. Our use: the Step by step arc; real screens only; numbered counter.
2. **Notion, feature walkthrough, 5 cards, Instagram, knowledge workers.** Card 1 a branded header; cards 2 to 4 meeting notes, project tracker and wiki as phone-scale screenshots; card 5 "Start free". Works because concrete use cases make an abstract "all-in-one" claim tangible. Our use: the Feature walkthrough arc, but with a real hook on card 1 instead of a logo header.
3. **Linear, problem / solution stack, 4 cards, LinkedIn and Meta.** Card 1 a headline; cards 2 and 3 pain vs fix side by side in the UI; card 4 a 14-day free trial. Works because the contrast is visible in one look. Our use: the Problem / solution arc, without naming any competitor.
**How much apps use carousels** (sprites.ai reads of Meta Ad Library samples, Sept to Oct 2026): Headway 33% carousels in the creatives read (a library of many books fits a swipe), Duolingo 17%, Calm 10%, BetterMe 0% (all video). Carousels are a main format for some subscription apps and absent for others: test, don't assume.
**Benchmarks (third-party, directional):** median swipe from card 1 to card 2 about 62%, card 5 reached by about 22% (adlibrary.com citing Klaviyo); viewers who reach card 3 convert several times more often; a steep drop after card 4; 3 to 5 cards recommended for installs (RocketShip HQ); carousels fatigue at a lower frequency than video, so plan card refreshes. On TikTok, photo carousels reported about 1.8x the engagement of videos but fewer shares (Stack Influence, Dec 2025).
**Structures the sources agree on:** card 1 stands alone and teases · one idea per card · proof as a receipt (a screen, a result), not a testimonial · the last card adds no new info · continuity devices (counters, numbered steps, panoramas, a shared band) signal "more" · lock the order for stories · refresh by swapping the weakest card · vary one card at a time in tests.
lyra-copy-competitor-ad63.9 KB
View saved version →
---
name: lyra-copy-competitor-ad
description: "Copy a competitor's video ad for a mobile app in Lyra. Analyses the reference video in the team's video creative classification standard (Lyra's Creative Analysis node or Claude's own frame by frame teardown), takes every fact from the user's Brand Kit, offers ways to retell the reference, rewrites the script for the brand and the request, then generates the new video. Two modes, close remake (same beats, timing and shots) or free adaptation (same idea and structure). Use for \"copy this competitor ad\", \"make an ad like this one\", \"remake this video for my app\", \"do this TikTok / Reel for us\", \"analyse this ad and make ours\", a Meta Ad Library or TikTok link to a video, or any video reference to adapt. Static ads, banners and carousels go to lyra-copy-competitor-static. Core video rules come from lyra-video-ad-generation."
---
# lyra-copy-competitor-ad
Mini skill. Takes a video ad that works for someone else, finds out **why** it works, and rebuilds that mechanism for the user's app: their pain, their feature, their person, their words, their brand. Four jobs in order: **analyse** the reference (Step 1a) → **go to the Brand Kit** and take every fact from it (Step 1b) → **ask the user** how to retell the reference, with variations (Step 1c) → **rewrite** the script for the brand (Step 2) → **generate** the new video in Lyra.
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**Statics have their own skill.** A static reference (one image, a carousel, several statics) or a static made from a competitor video's key frame → `lyra-copy-competitor-static` (static teardown by Reference L, layout map, new prompt, Nano Banana Pro build, variants). This file is for video.
**The Brand Kit is never skipped.** Close remake or free adaptation, the new ad always gets its name, audience, pains, feature, person, words, claims, offer, colors and ending from the user's Brand Kit (and the user's words in this chat). The reference gives only the mechanism.
**This is a way of thinking, not a script.** The rules below are defaults and good practice. Use judgment: when a different structure, shot or line serves the user's app better, do it and say why in one line. Only a few things are fixed: the line between mechanism and identity (next section), truth (no invented claims, reviews or numbers; the competitor's claims are never ours), the Brand Kit's facts, Lyra's technical limits, and the user's explicit choices.
**Base skill first.** Everything not written here follows `lyra-video-ad-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, prompt rules, models (Reference A), brief and scenes (B), audio (C), app UI (D), consistency (E), prompt craft (F), errors (G), de-slop (H), Brand Kit (I), Meta app ads (J). This file only adds what is specific to copying a reference. If the two disagree, the user wins, then this file, then the base skill.
**Other skills for their parts.** Once the reference is understood, the new video is built by the rules of the format it belongs to:
- a person talking to the phone (UGC, talking head, vlog, skit, interview) → `lyra-ugc-video` for the person, place, camera setup, voice and speech;
- the first 1 to 3 s, or several openings on the copied body → `lyra-video-hooks`;
- app screens, UI motion, end card → `lyra-ui-motion-video` (UI fidelity is hard there and here);
- anything else (lifestyle, POV, cinematic, stylized) → the base skill.
---
## What we copy, what we never copy (hard)
A competitor's ad is a **proof that a mechanism works on this audience**, not material to reuse. We copy the mechanism, never the identity.
| Copy (the mechanism) | Never copy (the identity) |
|---|---|
| the concept and the angle (the bet the ad makes on the audience) | their brand name, app name, logo, icon, slogan, catchphrases |
| the hook mechanism (kind, first frame idea, first move, line structure) | their exact lines, captions and on-screen text (rewritten every time) |
| the structure and beat order (hook, pain, demo, proof, CTA) | their people: faces, look, voice; no lookalike actor, no cloned voice |
| timing and pacing (beat lengths, cut rhythm, a new stimulus every N s) | their footage: never re-cut, crop, trace or overlay their video or frames in our ad |
| shot types, framing, camera setup and moves | their UI, screens and features (our screens come only from our screenshots) |
| the format (UGC selfie, POV, split screen, skit, UI motion…) | their claims, numbers, ratings, reviews, awards, offer and price |
| the audio role (native speech vs VO, music energy, where the SFX hits) | their music track, jingle or sound logo (music is generated from a description) |
| the CTA position and type (soft spoken tip, end card) | their brand colors and trade dress as a whole look; their mascots or characters |
**Rewrite test for every line.** A line keeps its **job** (callout, confession, objection, proof, CTA) and may keep its **shape** ("POV: you…", a question with a stake, a list of three tries), but its words are new and built from the user's Brand Kit. No sentence of ours shares a run of about five words with theirs, unless it is an ordinary phrase anyone would say ("try it tonight"). If a line only works with their product, it doesn't go in.
**Look test for the whole video.** Would a viewer who saw both ads think ours is theirs, or made by them? Then too close: change the person, the place, the palette or the line until the answer is no. The mechanism can be the same; the ad must look and sound like the user's brand.
---
## Two modes: close remake or free adaptation
The user picks the mode in Step 1c, after the teardown and the Brand Kit. Recommend one with one line why. **Both modes are built on the Brand Kit**: the remake is the reference's ad told with the brand's name, pains and offer; the adaptation is the reference's idea retold for the brand's audience, in its tone, usually ending on the app.
| | **A. Close remake** | **B. Free adaptation** |
|---|---|---|
| What stays | the same beats in the same order, beat lengths within about ±0.5 s, the same shot types, framing, camera setup and moves, the same hook mechanism and format, the same audio role | the idea, the angle, the hook mechanism and the structure; everything else is redesigned for the brand |
| What changes | the app name, pain, feature, person, place, words, voice, music, palette, UI, CTA, offer and ending (all from the Brand Kit) | everything the remake changes (from the Brand Kit), plus the shots, the place logic, the number and length of beats, the format if a better one fits, and an ending of our own with the app |
| Pick it when | the reference is a proven winner (running a long time, often 60 days or more in Meta Ad Library), the same audience and category, and the mechanism fits the app truthfully | a different audience, category or positioning; the mechanism depends on something the user doesn't have; or the user wants "the idea, not a copy" |
| Risk | too close to the competitor (run the look test) | losing the thing that made it work (keep the hook mechanism and the beat order) |
| Test value | isolates execution: "does this format work for us too?" | tests the concept in our own voice |
Both modes can run as an A/B test on one teardown: same app card, one remake, one adaptation. Name them so the media buyer sees which is which.
---
## Step 1 additions: the reference and the request
1. **The reference video.** Ask for it if missing. Accepted sources:
- a video file in the chat or a public direct link to the file → `create_upload` ({url} for a link) → `attach_upload` into the workflow. Lyra takes MP4, WebM, MOV up to 200 MB, 1 minute and 4K;
- a Meta Ad Library, TikTok or Instagram page link: usually a web page, not a file, so it can't be fetched. Ask the user to download the video and send the file, or upload it in Lyra (`open_upload_widget`). Don't retry the page link;
- a **static ad** (one image or carousel cards) → hand over to `lyra-copy-competitor-static`;
- several references for one idea: one teardown per reference, then say what they share (the shared part is the mechanism).
Check `list_uploads` first: the user may have uploaded it already.
2. **Why this ad.** Ask in the same message, one line each, all optional: what do you like in it (the hook, the format, the pacing, the humour)? How long has it been running, and is it a known winner? Whose ad is it (the competitor's app, so we keep their name out of everything)? The ad copy, if they have it (title, caption, body, description from Meta Ad Library): it helps the analysis fill gaps. The mode question comes later, in Step 1c, once Claude knows the reference and the Brand Kit.
3. **The request.** What the user wants changed or kept ("same but for students", "in Portuguese", "30 s instead of 15", "our mascot instead of a person"). The user's request wins over the reference.
**Defaults (state, don't ask):** mode recommended by Claude, user picks · same length, ratio and platform as the reference (9:16, Reels / TikTok if unclear) · English, or the language the user asks for · models as the base skill (Seedance 2.5 for people, Seedance 2.0 for stylized or UI-led, 720p by default (1080p on the user's choice), sound on) · Nano Banana Pro for every image · no video reference connected to generation (see "Video reference" below) · an app ending (store-style end card or a phone moment with a real screenshot) offered in Step 1c · competitor's name only inside the "Reference teardown" note.
**Recommended first run:** A. Images first (character and keyframes), as in the base skill. The analysis itself runs before the plan.
---
## Step 1a: analyse the reference
Two paths, one standard. Use Path 1 when it's available, Path 2 when it isn't, and both when Path 1 leaves gaps. The result is always one **teardown** with two layers, saved in the user text node "Reference teardown":
- **Layer 1, creative classification:** one JSON object in the team's video ad analysis standard (Reference K at the end of this file: taxonomy, schema, rules). It says what the ad **is**, in fixed categories the team can compare and pattern-match across many ads.
- **Layer 2, production breakdown:** what Claude needs to **rebuild** it: shot list with times, person, camera setup, voice, pacing, don't copy list. Layer 1 alone isn't enough for a remake.
### Inputs and order of evidence (both paths)
- **Frames every 3 s across the whole video:** the primary source of truth for every visual field. Analyse the full arc (opening, middle, end, loop), never only the first frame.
- **Audio transcript, timestamped** (Whisper): secondary; the primary source for `hook_text` when the hook is spoken (narration, testimonial, dialogue).
- **Ad copy** (title, caption, body, description), when the user has it (Meta Ad Library shows it next to the video): tertiary, only to fill gaps not seen in the frames or heard in the transcript.
- Every field rests on evidence. Nothing is invented: a gap is marked "not seen" / "not heard" in layer 2, and in layer 1 the source field says `inferred` where the schema allows it.
### Path 1: Lyra's Creative Analysis node
Lyra has its own analysis node, **Creative Analysis** (action `pattern_import`): Upload Video → Creative Analysis → format, structure and hook of the reference. The MCP tools can **run** it and **read** it, but can't **create** it.
1. Look for it: `get_workflow` on the user's workflow (or the one they name). A Creative Analysis node already on the canvas → connect the attached reference upload to it if it isn't (`connect_nodes`), read its price, say it, run it after a yes (`run_node`, then `get_run_results` until done), read the output.
2. No such node → ask once: "Lyra's Creative Analysis node gives its own breakdown of the reference. Add an Upload Video and a Creative Analysis node on the canvas and tell me, or I can analyse the video myself. Which do you prefer?" Don't wait in silence: if the user prefers, go to Path 2.
3. **Output already in the standard** (Reference K) → it becomes layer 1 after a check: exact property names, exact enum values, all required fields, `visual_summary` first, `cta_custom_text` when `cta_type` is `custom`, 2 to 5 `key_claims` in the claim format, 2 to 3 hex colors, no extra properties. **Output in another shape** → map it into the standard. Where it's silent (a field, the shot list, exact timing, voice, camera setup), fill from Path 2 if you can, or mark "not in the analysis" and ask the user.
4. The node's output is a source, not the script. The rewrite (Step 2) is still written by Claude, by this file's rules, from the user's Brand Kit.
### Path 2: Claude's own analysis
Claude analyses the video itself when it can see it.
- **The file is in Claude's environment** (attached in the chat, or in a folder Claude can read) **and there is a shell with ffmpeg:**
- duration and size: `ffprobe`;
- cuts: `ffmpeg -i ref.mp4 -vf "select='gt(scene,0.3)',showinfo" -f null -`, read the timestamps;
- **frames for layer 1, every 3 s:** `ffmpeg -i ref.mp4 -vf "fps=1/3,scale=720:-1" frames3s/%03d.jpg`;
- **extra frames for layer 2:** one per cut, and about two per second in the first 3 s (the hook);
- **transcript with timestamps:** whisper if installed (for example `whisper ref.mp4 --model small --word_timestamps True --output_format json`); otherwise read the burned-in captions from the frames, or ask the user for the spoken text with rough times;
- **colors:** the 2 to 3 dominant colors across the frames as hex (a short script over the frames, for example k-means on downscaled pixels), most dominant first.
Then look at every frame in order and write both layers.
- **No shell, or the video can't be opened:** ask the user for screenshots about every 3 s (at least the first frame, each new shot and the last frame), the spoken words with rough times, and the ad copy if they have it. Build the teardown from them and mark what they don't cover.
- **Never describe what you didn't see or hear.** A teardown with honest gaps is better than an invented one.
### Layer 1: creative classification (JSON)
Written exactly by the standard in Reference K:
- **one valid JSON object**, the schema matched literally: exact property names, exact enum values, no additional properties, all required fields;
- **`visual_summary` first**: the full arc in time order (what opens, what the middle shows, how it ends or loops), concrete frames, presenter actions, scene and style shifts, key on-screen text and the spoken hook transcribed exactly; never a generic "the ad promotes…";
- **`key_claims`**: 2 to 5 items, each `"[exact element from the frames or transcript] — [the rhetorical mechanism: why it works, what resistance it removes]"`; a visual element doing the persuasion is described as what is shown; nothing that isn't in the frames or transcript;
- **frames first** for visual fields, the **transcript first** for a spoken `hook_text`, ad copy only for gaps;
- `cta_custom_text` whenever `cta_type` is `custom`; `color_palette` 2 to 3 hex codes, most dominant first.
In a pipeline that expects the raw object, return only the JSON, nothing before or after it. In this skill the JSON goes into the "Reference teardown" note, and the user gets a short readable version in Step 1c.
**How layer 1 feeds the rest of the skill:**
| Field | Used for |
|---|---|
| `visual_summary` | the base of the shot list (layer 2) and of the side by side script (Step 2) |
| `hook_type`, `hook_text`, `hook_source` | the hook mechanism to keep and its kind and type in `lyra-video-hooks`; the line itself is rewritten, never reused |
| `narrative_arc`, `scene_structure` | the spine and the beat order; one clip with "cut to" or separate clips (base Step 2 reasons) |
| `presenter_type`, `video_subject`, `has_human_face` | which skill builds it and who is on screen: `real_person_UGC`, `presenter_talking_head` → `lyra-ugc-video` · `app_screen_walkthrough`, `screen_only` → `lyra-ui-motion-video` · `animated_character` → stylized on Seedance 2.0 · `hands_only_POV` → hands-only shots, no face · `voiceover_only` → VO node over B-roll |
| `video_production` | the polish level and look: `UGC_handheld` → raw phone-real · `studio_directed`, `talking_head_produced` → elevated · `app_mockup_animated` → UI motion with design frames · `screen_recording_live`, `screencast_tutorial` → our real screenshots only, never a fake recording · `AI_generated_video` → still de-slop rules |
| `video_pacing`, `format` | the cut rhythm and the length (timing contract) |
| `audio_style` | native speech in the clip (`dialogue`), a VO node (`voiceover`), a music node (`music_only`, `mixed`), nothing (`silent`) |
| `on_screen_text_style`, `text_to_visual_ratio`, `copy_structure` | the Video Editor text plan (captions, headlines, lists); never in a generation prompt |
| `emotional_tone` | the tone of the new lines, inside the Brand Kit's tone of voice (the kit wins on a conflict) |
| `offer_framing`, `cta_type`, `cta_source` | the CTA slot, its type and where it sits; the content comes from the Brand Kit's offer (theirs is never reused; no offer in the kit → no offer) |
| `social_proof_type` | which proof slot the ad has; filled only with the Brand Kit's real proof, otherwise dropped or replaced by a demo |
| `key_claims` | the mechanism behind each claim (kept) and their exact wording (never reused); feeds "Their claims" and "Why it works" |
| `color_palette` | the reference's palette, replaced by the brand palette (look test) |
### Layer 2: production breakdown (template)
Short, factual, one line per field, in the same note under the JSON:
1. **Header:** platform · ratio · polish level (raw, elevated, stylized) · language · whose ad (internal only).
2. **The bet (one line):** "They bet [audience] will [action] because [concept] addresses [pain] through [mechanism]." This is what we copy.
3. **Hook detail (0 to 3 s):** kind (visual, verbal, combined) · first frame · first move · text on frame 1 · sound · awareness level it targets (`lyra-video-hooks`).
4. **Shot list** (one row per shot, times from the cuts):
| # | Time | Beat (hook, problem, solution, proof, offer, cta, end card) | Shot and framing | Camera setup and move | What happens | Spoken line | On-screen text | Sound | Cut to next |
|---|---|---|---|---|---|---|---|---|---|
5. **Person:** archetype (mirror, friend a step ahead, skeptic, insider, two people) · age range · look and energy · setting and time of day · voice (gender, age, accent, pace, energy).
6. **Pacing detail:** number of cuts · average shot length · where the energy rises · new stimulus every N s.
7. **Audio detail:** words per second · music (genre, tempo, energy curve, vocals or not) · SFX hits.
8. **The app in the ad:** how the product is shown (the change on the person, the result in life, the phone moment, real screens) · when · for how long.
9. **CTA and end:** spoken CTA, caption, end card.
10. **Their claims** (from `key_claims` and anything else said or shown, listed so we never reuse them).
11. **Why it works:** 2 to 3 short reasons.
12. **Don't copy list:** the identity elements of this ad by name (their app name, slogan, actor look, sound logo, mascot, color look).
13. **Can't be reproduced truthfully:** what depends on something the user doesn't have (a real review, a celebrity, a feature, a number, a physical product) and the nearest truthful version.
**Example (short, fictional).** Layer 1:
```json
{
"visual_summary": "Opens on a handheld front-camera selfie: a woman in her twenties drops onto a pillow in a dark bedroom, phone held above her face, and says \"I tried every sleep hack on TikTok.\" Text overlay: \"every. single. one.\" Three fast jump cuts follow (2.5 to 6 s), each closer: a mug of tea, earbuds in, counting on her fingers. At 6 s she turns the phone screen toward herself, not visible to the viewer, and says \"This one says asleep in 10 minutes.\" Cut at 10 s to B-roll: her eyes closed, the phone face down on the duvet. Ends at 13 s back on the selfie, smiling: \"It's free, just try it.\" Word-by-word captions at the centre throughout.",
"hook_type": "UGC_testimonial",
"hook_text": "I tried every sleep hack on TikTok.",
"hook_source": "transcript",
"narrative_arc": "problem_agitate_solve",
"presenter_type": "real_person_UGC",
"scene_structure": "single_continuous",
"on_screen_text_style": "mixed_overlays",
"video_production": "UGC_handheld",
"video_subject": "presenter_talking_head",
"format": "video_6_15s",
"emotional_tone": "empathetic_relatable",
"copy_structure": "story_arc_narrative",
"offer_framing": "free_trial",
"cta_type": "try_free",
"cta_source": "transcript",
"key_claims": [
"\"I tried every sleep hack on TikTok.\" — a confession of failure puts her on the viewer's side before any product appears; the viewer's own failed tries become the proof that the problem is real.",
"Three jump cuts: tea, earbuds, counting on her fingers — the old ways shown fast and closer each time, so the frustration builds without a word of explanation.",
"\"This one says asleep in 10 minutes.\" — a specific time promise turns a vague hope into a result the viewer can test tonight.",
"Eyes closed, phone face down on the duvet — the result is shown on the person, not on the screen; sleep itself is the demo."
],
"social_proof_type": "user_quote",
"color_palette": ["#1B2233", "#E8B27A", "#F2F2F2"],
"has_human_face": true,
"text_to_visual_ratio": "visual_dominant",
"video_pacing": "medium",
"audio_style": "dialogue"
}
```
Layer 2:
> Header: TikTok · 9:16 · raw · English · a sleep app (internal).
> Bet: they bet women 20 to 30 who can't fall asleep will install because a tired confession at 2 am makes the app feel like a friend's tip.
> Hook detail: combined · she drops onto the pillow · text "every. single. one." · pillow thump · problem aware.
> Shots: 5 cuts, average 3 s; 0 to 2.5 s selfie in bed (handheld, arm's length); 2.5 to 6 s three jump cuts, one per hack, closer each time; 6 to 10 s phone moment, screen toward her; 10 to 13 s eyes closed, phone on the duvet (B-roll); 13 to 15 s back to selfie, soft CTA.
> Audio detail: about 2.4 words per second; no music; room tone.
> Their claims: "asleep in 10 minutes" (theirs, never reused).
> Why it works: pain in 2 s in her words; the three failed hacks are the viewer's own history; no screen needed.
---
## Step 1a (static): moved
Static references (one image, a carousel, several statics) and statics made from this video's key frame are analysed and built by `lyra-copy-competitor-static`: the static standard (Reference L), the measured layout map, the transfer map by zones, the Nano Banana Pro prompt and the variants. When a video copy and a static copy of the same reference are wanted, run this skill for the video and that skill for the static, on the same Brand Kit sheet.
---
## Step 1b: the Brand Kit (always, in both modes)
Right after the teardown, before a single line is rewritten, Claude goes to the Brand Kit. This step is never skipped, in the remake as much as in the adaptation: the reference says **how** the ad works, the Brand Kit says **what** the new ad is about and **who** it talks to. Nothing is taken from the competitor's brand, and nothing is invented to fill a gap.
**Which Brand Kit** (base Reference I):
1. A Brand Kit given in the chat → use it.
2. Otherwise check what the workflow has: `get_workflow` (the kit assigned to the workflow) and `list_brand_kits` (the kits in the workspace).
3. **Exactly one** candidate → confirm in one line: "I'll make it for {kit name}, right?"
4. **More than one** (several kits on the workflow, or none assigned and several in the workspace) → ask which one, with their names. Never mix two kits in one ad. Two apps wanted → two separate builds, one kit each.
5. **None** → ask once: send it here, or should I check and connect one of the workspace's kits? Or type the essentials: app name, what it does, audience, pains, the feature to show, approved claims, offer, tone, logo and screenshots.
6. Once chosen, `assign_brand_kit` on the workflow if it isn't assigned yet.
**Read it fully and fill the Brand Kit sheet** (top of the "Transfer map" note), one line per field:
app name exactly as written, and how it's pronounced · what it does · audience and segments · pains in their words · desires · objections · features (mark the one that answers the reference's pain) · approved claims and proof · forbidden claims · offer and CTA · tone of voice · positioning (sets the polish level) · colors and fonts · assets (logo, icon, screenshots, end card, store badges) · markets and languages · must include / must exclude.
**Gaps.** A missing pain → 3 to 5 pain hypotheses in the audience's words, to confirm (as in `lyra-video-hooks` Step 1). Missing screenshots → the screen stays hidden, or ask for them. No approved claim → no claim. A gap is never filled from the competitor's ad.
**Conflicts.** The user's words in the chat win over the kit; name the conflict in one line. If the reference's mechanism clashes with the kit (a chaotic brainrot ad for a premium finance brand, a body before/after for a health app, a must exclude), say so and propose the adaptation that keeps the mechanism inside the brand's rules.
## Step 1c: ask the user, and offer variations
One message, after the teardown and the Brand Kit sheet, before any build. Every option in it is written with the Brand Kit's real name, audience, pain, feature and offer, so the user sees their own ad, not an abstract plan.
1. **The reference in 3 to 4 lines**, from both layers: the bet, the hook (`hook_type`, the hook line), the arc (`narrative_arc`), the format and look (`presenter_type`, `video_production`), why it works (`key_claims`).
2. **The mode question**, both options told in Brand Kit terms, with a recommendation:
- **A. Close remake:** "the same ad beat for beat, but it's {app name}: {pain from the kit}, {feature}, {persona from the kit's audience}, {offer}, ending on {app ending}."
- **B. Free adaptation:** "the same idea and hook, retold for {audience from the kit} in {tone from the kit}, with our own scenes and an ending with {app name}."
3. **2 to 3 variations of how to present the reference our way**, one line each, each built on the Brand Kit, one recommended. Ways to vary (pick what fits the reference and the kit):
- another pain or segment from the kit (the same body for "students" and for "night-shift workers");
- another persona or place (a different archetype from the audience, the pain moment in another spot);
- problem first vs app first (the app named in the first 2 to 3 s);
- another format for the same mechanism (UGC → UI motion, split screen, talking object);
- another hook on the same body (`lyra-video-hooks`, mode A);
- another medium: a static ad from the video's key moment, one concept tested across placements (built by `lyra-copy-competitor-static`);
- another ending (see 4).
4. **The ending with the app.** Unless the reference already ends on the product in a way the user wants to keep, offer an app ending and ask which: a **store-style end card** (`lyra-ui-motion-video`) with the kit's icon, app name, benefit line and CTA · a **phone moment** with a real screenshot of the key screen · the **person with the result** and the app name in the caption.
5. **Only the questions still open**, in the same message: missing kit fields, screenshots, language, length.
Each variation the user picks becomes its own concept (`C1`, `C2`…) with its own transfer map, script and Video Editor; more takes of one variation are `count`, not new concepts (base rule).
**Example (short, fictional app Calmly).**
> Reference: 15 s UGC storytime, a tired confession in bed at 2 am, three failed sleep hacks, the app as the last try, a soft CTA. It works because the pain lands in 2 s in her own words.
> Brand Kit: Calmly, the only kit in this workspace. Make it for Calmly, right?
> A. Close remake: the same five beats and timing, but it's Calmly: Mia, 21, a student whose brain won't stop at 2 am, tries tea, podcasts, counting sheep, then the 5-minute wind-down timer; ends on the Calmly end card "Sleep in 5 minutes · Get".
> B. Free adaptation: the same confession hook, retold as a walk and talk the next morning, "I actually slept", ending on the phone with your real timer screen.
> Variations: V1 the remake above (recommended: proven format, same audience) · V2 the same body for the kit's second segment, young nurses after night shifts · V3 app first: she opens Calmly in the first 2 s, then the confession.
> Ending: the Calmly end card, or the phone with your timer screenshot? Send me the timer screenshot if the screen should be seen.
---
## Step 2 addition: the transfer map and the new script
### The transfer map
Before writing a line, map each part of the reference to the user's app, for the mode and variation the user picked in Step 1c. The "Ours" column comes **only** from the Brand Kit sheet (Step 1b) and the user's words. One line per element: **reference → ours · keep / translate / drop · why**. It goes into the "Transfer map" text node and, short, into the concept.
| Element | Reference | Ours (from the Brand Kit) | Action |
|---|---|---|---|
| Audience | women 20 to 30, can't sleep | students 18 to 25, can't switch off | translate |
| Pain | can't fall asleep | brain won't stop at 2 am | translate |
| Hook mechanism | combined: drop onto pillow + confession | same mechanism, new beat and line | keep (remake) |
| Old way beat | three failed hacks | tea, podcasts, counting sheep (from reviews) | translate |
| Feature | their sleep stories | Calmly's 5-minute wind-down timer (real screenshot) | translate |
| Claim | "asleep in 10 minutes" | none approved → result shown on the person, no number | drop |
| Person | their actress | Mia, 21, character card from our audience | translate |
| CTA | "it's free, just try it" | real offer from the Brand Kit: "It's free. Try it tonight." | translate |
| Music | none | none | keep |
| Ending | soft CTA on her face | Calmly end card: icon, "Sleep in 5 minutes", Get (picked in Step 1c) | translate |
**Rules for the map:**
- Every beat of the reference has a row. A beat we drop is written as dropped, with the reason.
- Their pain becomes the **closest real pain** in the user's pain map, said in the user's audience's words. If none is close, the mechanism doesn't transfer: say so, and offer the adaptation mode or another reference.
- Their feature becomes **one real feature** of the user's app that answers that pain. Never borrow a feature the app doesn't have.
- Their claims are dropped by default; a claim comes back only if the user's Brand Kit has its own approved one.
- Their person becomes a persona from the user's audience (`lyra-ugc-video` casting), different in look from theirs.
- Their palette and look become the user's brand palette, at the same polish level.
### The new script
Written by Claude into the "Script" text node (base Reference B), from the transfer map.
- **Timing contract.** Remake: the same beats in the same order, each beat within about ±0.5 s of the reference, the same total length. Adaptation: the total length from the request, beats as the new structure needs. Durations always add up exactly.
- **Word budget per beat.** Count the reference's words per beat and match them closely, then check against the base pace (about 2.5 words per second, speech ending about 1 s before the clip ends). A translation into another language usually runs longer: shorten it, never rush it.
- **Same job, new words.** Each line keeps its job and may keep its shape; the words come from the Brand Kit and customer words. Run the rewrite test on every line.
- **Hook first.** Write the hook with `lyra-video-hooks` (line checks, 6 to 10 words, text 2 to 6 words marked for post). In remake mode it keeps the reference's hook kind and mechanism; in adaptation mode it may change if a stronger hook for this pain exists, said in the plan.
- **On-screen text and captions** are rewritten too, marked for post (Video Editor only, never in a prompt).
- **Side by side in the concept.** Show the user the script next to the reference, beat by beat:
| Beat | Time | Reference (what it does) | Ours (what we do and say) | Kept | Changed |
|---|---|---|---|---|---|
The concept the user approves (base Step 2) has: the Brand Kit it is built on · the mode and variation picked in Step 1c · transfer map in short · the side by side script · the ending · the plan table · the model question.
---
## Best way to build it
The format of the reference decides the build. The user's explicit choices override any row. Models and prices: base Reference A.
| If the reference is | Build by | Graph | Models |
|---|---|---|---|
| UGC, talking head, storytime, vlog, skit, interview | `lyra-ugc-video` | character image (our persona, count 2) → one Seedance 2.5 clip, speech in quotes, the reference's cuts written as "cut to" → B-roll and UI insert if the reference had them → Video Editor | nano-banana-pro · seedance-2.5 |
| A hook-led ad, or the user wants several openings on the copied body | `lyra-video-hooks` (mode B, or mode A on the new body) | as the hook skill | as the hook skill |
| UI motion, floating phone, demo of screens | `lyra-ui-motion-video` | our screenshots → design frames → one Seedance 2.0 frame clip per shot → end card → Video Editor | nano-banana-pro · seedance-2.0 |
| Lifestyle, POV, cinematic, real people without speech | base skill | character image → one multi-shot clip with "cut to" in the reference's order → VO + music → Video Editor | nano-banana-pro · seedance-2.5 |
| Illustration, cartoon, stylized, moving text | base skill | keyframe per shot in our style → Seedance 2.0 with frames → Video Editor | nano-banana-pro · seedance-2.0 |
| The mechanism is one signature movement (a dance, a gesture, a fall) | base skill | our character image + **a motion video we own or film**, never their footage → Kling 3.0 Motion Control; speech parts stay on Seedance 2.5 | kling-v3-motion-control · seedance-2.5 |
| Longer than 30 s | base Reference A | the script split in two parts at a natural beat, same references, two clips, joined in the Video Editor | seedance-2.5 |
| A split screen, chat thread or comment reply | `lyra-video-hooks` (catchy formats) | as the hook skill; bubbles and comments stylised, our own text | nano-banana-pro · video_composer |
**Shots, not micro clips.** As in the base skill, one multi-shot clip by default; split only for the base reasons (over 30 s, a UI insert, different models or exact frames, a failed shot, the user asks). A remake with many quick cuts still fits in one Seedance 2.5 clip when the cuts are written as "cut to" with their lengths.
### Video reference (the competitor's video in the generation node)
By default the reference video is **only analysed**: it sits in Section "Reference" and is **not connected** to any generation node. The montage comes from the script Claude writes (shot list with times), as the base skill's reference policy says.
Only in **remake mode**, and only when the user asks for the rhythm to be copied closer, the reference can go into the Seedance clip as **one video reference used as an editing reference only** (cuts, pacing, camera rhythm). Then:
- say once that it can leak their look (faces, outfit, colors, text, logo) into ours;
- write its job first in the prompt: "[Video1] is an editing reference only: copy its cut rhythm, shot lengths and camera energy. Do not copy its people, faces, clothing, places, colors, text, logos or sound.";
- check the result with the user against the "Don't copy list" before anything else; any leak → disconnect it and rerun with the script only.
Never use their footage as a frame, a layer, a B-roll or a motion source.
**Layout.** Section "Reference" (the uploaded reference, the Creative Analysis node if any, "Reference teardown" and "Transfer map" notes; nothing here feeds generation by default) → then the base layout: Sources (script note, character, screenshot uploads) → Images → Clips → Audio → Video Editor. Labels: "Ref: sleep app UGC (analysis only)", "Script: remake C1", "Mia: bed 2 am (clip)", "Final: C1 remake · storytime sleep".
---
## Prompt rules (copy)
| Node | Write | Avoid |
|---|---|---|
| Reference teardown (text) | layer 1: one JSON object by Reference K; layer 2: the production breakdown; facts only, gaps marked "not seen" / "not heard" | guesses; enum values that aren't in the schema; paraphrased claims; long praise of the ad |
| Transfer map (text) | one row per element: reference → ours → keep / translate / drop → why | their lines copied in as "ours" |
| Script (text) | the new lines per beat with times and word counts; captions marked for post; the side by side table | their exact words, product name, slogan, claims |
| Character image | our persona's card from the user's audience (UGC rules); the reference's framing and camera setup described in words | their actor's description ("like the girl in the ad"); a lookalike; their outfit or set |
| Video clip | roles of references first ([Image1] is our character…), then the reference's shot plan **in words**: framing, camera setup, action per beat, "cut to" with lengths, our lines in quotes, sound line (when someone speaks: voices and scene sounds only, "no music, no background music, no soundtrack, no score", base Reference C), end state | "as in the reference video", "same as the competitor"; their text, logos, colors; a video reference without its job stated |
| Music | genre, tempo and energy curve of the reference's track, described | their track, the song name, the artist name (error) |
| VO | our words only, sized to the beat timing, ~1 s shorter than the video | their wording translated line by line |
Every prompt is self-contained (base rule): describe the shot itself, never "like the reference". The model never sees the competitor's ad unless a video reference is connected on purpose.
---
## Run options (copy)
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes, per option. The analysis comes first and on its own: **Path 1** costs what the Creative Analysis node shows next to Run (say it before running) · **Path 2** costs no credits. Then: **A. Images (recommended):** character and keyframes · **B. Clips** for the picked images, with VO and music · **C. Everything** → Video Editor. Remake and adaptation together: the same options, multiplied by two.
---
## Truth, rights and brand safety
- The competitor's ad is a reference for analysis. Their footage, frames, audio, music and text are never part of our ad.
- No competitor name, logo or product in our ad, and no comparison with them by name. A comparative ad that names a competitor is a legal question for the user's team, not a default; this is not legal advice.
- Their claims, numbers, ratings, reviews and awards are theirs. Ours come only from the user's Brand Kit or the user.
- No lookalike of their actor or creator, no cloned voice, no copy of their mascot or characters.
- Trends and formats are free to use; specific creative work isn't. When in doubt, move the ad further from the reference (adaptation mode).
- AI people follow `lyra-ugc-video` Truth and disclosure: never presented as real customers; remind the user once about the platform's AI label.
- **Brand safety** (Lyra's System Preamble, base Reference B): no profanity, no political statements, no unsubstantiated health claims, and no digs at the competitor even without its name. The Brand Kit's **forbidden claims are enforced absolutely**, in every line, caption, visual and VO, even when the reference makes that claim; if the user asks for one, say once that it is on the kit's forbidden list and leave it out unless the user confirms the kit is outdated.
---
## Deliverable and naming
1. A "Reference teardown" note and a "Transfer map" note in Section "Reference".
2. The new "Script" note with the side by side table.
3. All planned images, clips, audio and one Video Editor per final (two when remake and adaptation run as an A/B).
Name every final with a code the media buyer can paste into Ads Manager: `B{batch}-A:{angle}-F:Copy-{format}-{Remake|Adapt}-R{reference}-C{concept}`, e.g. `B5-A:BrainWontStop-F:Copy-UGCStorytime-Remake-R1-C1`. Static finals are named by `lyra-copy-competitor-static`. Add `H{n}` when hooks from `lyra-video-hooks` are tested on it, and `P{n}` for personas. The competitor's name stays out of the code; `R1` points to the teardown note.
---
## Common mistakes (copy)
| Mistake | Prevention |
|---|---|
| Script written before the reference is understood | Teardown first, then the Brand Kit, then the questions, then the transfer map, then the script |
| Brand Kit skipped "because it's a close remake" | Step 1b in both modes; every name, pain, feature, claim and offer from the kit |
| Several kits on the workflow or in the workspace, one picked silently, or two mixed | Ask which kit; one kit per ad |
| Gaps in the kit filled from the competitor's ad | Pain hypotheses to confirm, hidden screen, no claim |
| Mode asked as an abstract choice | Both modes and 2 to 3 variations told with the kit's real name, audience, pain and offer |
| No app at the end | Offer the app ending in Step 1c: end card, phone moment or result + caption |
| Classification by the first frame only, or enums invented | Frames every 3 s across the full arc; values only from Reference K |
| Claims paraphrased or added from the ad copy | `key_claims` quote the frames or transcript exactly; ad copy only fills gaps |
| A static reference built with this video skill | `lyra-copy-competitor-static` |
| The teardown describes things Claude didn't see or hear | "Not seen" / "not heard" + ask; frames and transcript only |
| Waiting for the Creative Analysis node that isn't there | Ask once, offer Path 2, keep moving |
| Their lines translated or lightly reworded | Same job, new words; rewrite test on every line |
| Their claim ("asleep in 10 minutes") reused for our app | Their claims listed and dropped; ours only from the Brand Kit |
| A feature borrowed from their app | One real feature of ours per transfer map; no fit → adaptation or another reference |
| Our actor looks like theirs, same outfit, same room | Persona from our audience; look test |
| Their palette and look kept, so our ad reads as theirs | Our brand palette at the same polish level |
| Their video connected to generation by default | Analysis only; video reference only on request, in remake mode, with its job stated and a leak check |
| Their footage used as B-roll, frame or motion source | Never; for motion transfer use footage we own |
| "As in the reference video" in a prompt | Describe the shot in words; prompts are self-contained |
| Remake drifts in timing or beat order | Timing contract: same beats, about ±0.5 s each |
| Adaptation loses the hook mechanism | Keep the bet, the hook mechanism and the beat order |
| Their song or artist named in the music brief | Describe genre, tempo and energy; no names |
| Competitor's name in the final's name or on screen | Internal teardown note only; `R{n}` in the code |
| A 60 s reference promised in one clip | Two parts joined in the Video Editor (base Reference A) |
| Page link from Ad Library retried as a file | Ask for the downloaded file or an upload in Lyra |
## Quality gates (copy)
- **Stage 0 (teardown, Brand Kit, map and script; Claude checks before sending):** the Brand Kit chosen and confirmed (asked when there was more than one)? Its sheet filled, gaps marked? Mode, variation and ending picked by the user, all told in the kit's terms? Layer 1 a valid JSON object by Reference K (exact names and enums, all required fields, `visual_summary` first, claims in the claim format, analysed on frames every 3 s across the whole video)? Every field of layer 2 filled or marked as a gap? The bet in one line? Every reference beat mapped (keep, translate, drop)? Pain and feature real for our app? Their claims dropped? Lines pass the rewrite test? Timing adds up (remake: each beat about ±0.5 s)? Word counts fit at a calm pace? Don't copy list written?
- **Stage 1 (images):** our persona from our audience, clearly not their actor? Our palette and setting? The reference's framing and camera setup there? (Plus the base, UGC or UI stage 1 checks.)
- **Stage 2 (clips):** beats in the reference's order and rhythm? The hook lands like theirs, in our words? If a video reference was used: no leak of their people, colors, text or logo? (Plus the format's stage 2 checks.)
- **Stage 3 (final), side by side:** ask the user to watch both one after the other. Same mechanism, same energy in the first 3 s? Is it clear in one watch what **our** app does? Anything that still says "competitor" (a phrase, a look, a sound, a color)? Promise matches our store page? Captions, CTA, 9:16, planned resolution, length, name with its code? AI label reminder given?
## After the test
Read the test as in `lyra-video-hooks` (After the test). A reference that wins for a competitor is a hypothesis for us, not a promise: judge ours by our own KPIs (hook rate, hold rate, cost per trial, payers). Say what won: the mechanism (the copy works → make more on this bet with new hooks, personas, languages) or not (the mechanism doesn't transfer to our audience → note it, try the adaptation or another reference). Save the teardown and the result to the project's hook or creative repository, so the next copy starts from what we already learned.
---
## Reference K. Video ad creative analysis standard (layer 1)
The team's standard for classifying a video ad. Claude follows it word for word for layer 1 of every teardown, and checks the Creative Analysis node's output against it.
**Role.** A performance marketing creative analyst for video ads: extract structured classification data from the creative.
**Inputs.** Frames extracted every 3 s across the whole video (primary source of truth; analyse the full arc, not just the first frame) · the audio transcript, timestamped, from Whisper (secondary: spoken hooks, narration, testimonial content) · optional ad copy fields: title, caption, body, description (tertiary support only).
**Core requirements.** Exactly one valid JSON object that conforms to the schema · no preamble, markdown fences or explanation when the raw object is requested · exact property names, exact enum values, no additional properties · `visual_summary` always the first field · outputs limited to evidence in the creative and these rules.
**Priority rule.** Frames are the source of truth for visual fields · the transcript is the source of truth for `hook_text` when the hook is spoken · title, caption, body only fill gaps not visible in the frames or transcript · the full arc matters: opening, middle and end.
**What to examine before classifying.** All frames in sequence: what appears in the first 1 to 3 s (hook setup) · how the narrative or visual structure develops across scenes · whether a presenter is shown, and in what context · the dominant visual subject across the full duration · which on-screen text overlays appear and when · how the video ends or loops.
**`visual_summary`.** A concrete visual-mechanical description of the full arc, not a generic marketing summary: in time order (what opens, what the middle shows, how it ends) · specific frames, on-screen text, presenter actions, scene changes · key on-screen text and the spoken hook transcribed exactly · distinct scene or style shifts named ("hard cut to full-screen graphic slide", "loops back to opening frame") · no "the ad promotes…" unless tied to the concrete mechanic.
**`key_claims`.** For each claim: (1) quote or closely reference the exact language, phrase or visual element in the frames or transcript, never paraphrased, never invented; (2) explain the rhetorical mechanism, how this element communicates value or overcomes resistance. Format: `"[exact element from creative] — [explanation of why this works / what it communicates]"`. A visual element doing the persuasion is described as what is shown and why it works as a claim. No claims the frames or transcript don't support.
### Taxonomy
**`hook_type`** (the primary persuasion mechanic of the opening 3 s): `problem_solution` names a pain, then frames the product as the fix · `before_after` shows or implies a state change · `social_proof` leads with others' behavior, ratings or adoption · `UGC_testimonial` first-person user voice or a real person sharing their experience · `curiosity_gap` withholds information to create a gap that demands resolution · `fear_urgency` anxiety, loss aversion, fear of missing out · `question` a direct question to the target audience · `statistic_claim` a specific number, percentage or data point · `POV_first_person` puts the viewer in the scenario with "you" or first person · `tutorial_how_to` a promise to show how to do something · `unboxing_reveal` sequential discovery or unwrapping · `comparison_vs` contrasts two options, brands or states · `transformation` the journey or change process, not just the endpoint · `day_in_life` follows a character through a scenario · `GRWM_get_ready` get-ready-with-me, product in a routine · `reaction` a visible emotional reaction · `myth_busting` challenges a common belief · `listicle` numbered or bulleted list as the structure · `controversy_hot_take` provocative or polarizing opening · `authority_expert` credentials, expertise or professional context · `emotional_story` a narrative with an emotional arc · `product_demo` the product shown in use as the immediate hook · `challenge` invites the viewer to try something.
**`hook_source`** (where the hook text was found): `on_screen_text` overlay on the frame · `transcript` spoken by a presenter or VO, not visible as text · `title` · `caption` · `body` · `description` (ad copy fields) · `inferred` from the overall intent, no explicit source.
**`narrative_arc`** (story structure across the full video): `talking_head_direct` presenter speaks to camera the entire video, no scene structure · `hook_demo_cta` hook scene → product demonstration → end card or CTA · `hook_loop` opens and closes on the same or near-identical scene, built for replay · `problem_agitate_solve` the pain is shown and worsens before the solution · `listicle_sequential` numbered items one by one · `multi_segment_compiled` 3+ distinct scenes or styles stitched together, often by VO · `transformation_reveal` linear before to after, payoff at the end · `testimonial_monologue` one person's story start to finish, no cutaways · `social_proof_compilation` several testimonials or reactions edited together · `unboxing_reveal` tension builds toward a reveal · `tutorial_step_by_step` ordered steps · `comparison_walkthrough` alternates option A and option B · `educational_explainer` structured teaching, instructor pacing · `single_shot_loop` one continuous take, no edits, built to loop · `GRWM_routine` product integrated in a get-ready routine · `reaction_to_content` presenter reacts to something shown on screen.
**`presenter_type`** (the primary on-screen presence): `real_person_UGC` selfie-style, phone-held, casual · `real_person_expert` a person in an authority setting (uniform, lab, trade show, professional tools) that signals credibility without stating it · `real_person_lifestyle` a person in an aspirational context, not speaking to camera · `celebrity_influencer` a recognizable public figure or verified creator · `AI_avatar` a synthetic human presenter · `animated_character` illustrated or cartoon presenter · `voiceover_only` a voice, no person on screen · `hands_only_POV` first-person hands, no face at any point · `none` no human presence.
**`scene_structure`** (spatial and temporal organization): `single_continuous` one location, one setup, no meaningful scene cuts · `two_scene_ab` exactly two scenes with a clean A to B transition · `hook_plus_demo` a short hook scene, then an extended demo · `multi_segment_complex` 3+ scenes with meaningfully different styles or locations · `looping_hook` opens and closes on identical or near-identical frames · `rapid_montage` many clips under 2 s each · `screen_only` the whole video is an app or screen recording.
**`on_screen_text_style`**: `subtitle_captions` word-by-word captions following speech, at the bottom · `headline_overlays` large standalone text blocks, not following speech · `kinetic_typography` text animation is the main visual · `app_ui_labels` text inside a shown app interface · `infographic_labels` text in a designed full-screen graphic slide · `mixed_overlays` captions and headlines together · `emoji_text_hybrid` emoji used prominently with text · `none` no text overlays.
**`video_production`** (dominant production style): `UGC_handheld` phone-shot throughout, natural, unpolished · `studio_directed` professional light, controlled set, directed shots · `screen_recording_live` a real device screen captured as is, status bar and real UI visible · `app_mockup_animated` polished animation of app UI, not a real recording · `graphic_animation_only` motion graphics only, no live footage · `mixed_live_and_graphic` real footage with designed graphic slides · `mixed_UGC_and_screen` UGC footage with app screen cutaways · `stock_footage_produced` stock clips with branded graphics or VO · `AI_generated_video` visibly AI-generated throughout · `documentary_cinematic` cinematic, intentional handheld, observational · `slideshow_static_frames` static images edited as video · `screencast_tutorial` screen recording with cursor or taps, tutorial style · `talking_head_produced` a person on camera, professionally lit and directed · `animated_explainer` fully animated characters or scenes.
**`video_subject`** (the primary narrative subject across the video): `presenter_talking_head` faces camera throughout, direct address · `presenter_with_product` holds or demonstrates the product · `presenter_lifestyle_scene` in context, product integrated naturally · `hands_only_POV` hands throughout, no face · `app_screen_walkthrough` app UI is the main subject · `product_hero_rotating` the product alone, often moving or rotating · `before_after_sequence` two states in time order, not a split frame · `transformation_reveal` gradual reveal, payoff held late · `animated_character_scene` an illustrated or synthetic character drives it · `voiceover_with_broll` no dominant subject, VO over supporting footage · `infographic_sequence` designed full-screen slides · `social_feed_scroll` a simulated feed, comments or reactions · `multi_person_compilation` different people across scenes · `environment_establishing` a place is the subject · `text_kinetic_sequence` typography animation throughout · `reaction_overlay_scene` a person reacts to content shown at the same time.
**`format`** (duration bucket): `video_under_6s` bumper or loop · `video_6_15s` short, hook-only or awareness · `video_15_30s` standard short performance · `video_30_60s` room for demo or narrative · `video_over_60s` long story or deep demo.
**`offer_framing`**: `price_anchor` a high reference price makes the real one feel cheap · `free_trial` leads with a no-cost trial · `percentage_discount` · `dollar_discount` (a currency amount) · `BOGO` buy one get one · `limited_time_urgency` a restricted time window · `scarcity` limited quantity · `value_stack` many inclusions make the value feel large · `money_back_guarantee` · `free_shipping` · `bundle_deal` · `subscription_savings` recurring billing framed as cheaper · `no_offer_brand_only` no economic proposition · `comparison_pricing` a competitor's price next to own · `pay_what_you_want`.
**`cta_type`**: `learn_more` · `shop_now` · `try_free` · `get_started` (onboarding, apps, SaaS) · `download` · `sign_up` · `subscribe` · `buy_now` · `book_now` · `get_offer` · `claim_deal` · `see_more` · `send_message` · `watch_more` · `swipe_up` · `custom` any other CTA, its exact text in `cta_custom_text`.
**`cta_source`**: `on_screen_text` · `transcript` · `title` · `caption` · `body` · `description` · `inferred` (no explicit CTA, inferred from the landing intent).
**`emotional_tone`** (dominant register): `aspirational` an idealized future state · `fear_based` anxiety, threat, loss · `humorous_playful` · `educational_informative` calm, factual · `urgent_FOMO` act now or miss out · `calm_trust` measured, reassuring · `provocative_edgy` · `empathetic_relatable` mirrors the viewer's feelings without judgment · `luxurious_premium` · `nostalgic` · `inspirational_motivational` · `casual_conversational` a friendly message from a peer.
**`copy_structure`** (spoken and on-screen text across the video): `headline_only` one dominant message · `headline_plus_subtext` · `long_form_story` an extended narrative or monologue · `minimal_no_text` only a logo and brand mark · `bullet_benefits` features or benefits one after another · `story_arc_narrative` a mini story with beginning, middle, resolution · `question_answer` · `listicle_numbered` · `social_proof_quote` a user, expert or third-party quote as the main copy · `data_driven_stats` statistics as the main copy.
**`video_pacing`**: `single_shot` one take, no cuts · `slow_cinematic` long takes, few cuts · `medium` cuts every 3 to 5 s · `fast_cuts` cuts every 1 to 2 s · `rapid_montage` sub-second cuts.
**`audio_style`**: `dialogue` the person on screen speaks, lip sync · `voiceover` an off-camera voice, no lip sync · `music_only` · `silent` · `mixed` dialogue or VO with music under it.
**`social_proof_type`** (even as a secondary element): `none` · `user_quote` a quote from a real or simulated user, spoken or on screen · `star_rating` · `user_count` users, downloads, customers or reviews · `award` an award, badge, certification, App of the Year signal · `celebrity` a known figure, influencer or verified creator.
**`text_to_visual_ratio`**: `text_heavy` text dominates most frames · `balanced` · `visual_dominant` text is minimal (logo, short CTA or captions only) · `no_text`.
Plus: **`color_palette`** 2 to 3 dominant hex colors, most dominant first · **`has_human_face`** true if a face is visible in any frame · **`key_claims`** 2 to 5 items in the claim format · **`cta_custom_text`** required when `cta_type` is `custom`.
### Schema
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Video Ad Creative Analysis",
"type": "object",
"properties": {
"visual_summary": { "type": "string" },
"hook_type": { "type": "string", "enum": ["problem_solution","before_after","social_proof","UGC_testimonial","curiosity_gap","fear_urgency","question","statistic_claim","POV_first_person","tutorial_how_to","unboxing_reveal","comparison_vs","transformation","day_in_life","GRWM_get_ready","reaction","myth_busting","listicle","controversy_hot_take","authority_expert","emotional_story","product_demo","challenge"] },
"hook_text": { "type": "string" },
"hook_source": { "type": "string", "enum": ["on_screen_text","transcript","title","caption","body","description","inferred"] },
"narrative_arc": { "type": "string", "enum": ["talking_head_direct","hook_demo_cta","hook_loop","problem_agitate_solve","listicle_sequential","multi_segment_compiled","transformation_reveal","testimonial_monologue","social_proof_compilation","unboxing_reveal","tutorial_step_by_step","comparison_walkthrough","educational_explainer","single_shot_loop","GRWM_routine","reaction_to_content"] },
"presenter_type": { "type": "string", "enum": ["real_person_UGC","real_person_expert","real_person_lifestyle","celebrity_influencer","AI_avatar","animated_character","voiceover_only","hands_only_POV","none"] },
"scene_structure": { "type": "string", "enum": ["single_continuous","two_scene_ab","hook_plus_demo","multi_segment_complex","looping_hook","rapid_montage","screen_only"] },
"on_screen_text_style": { "type": "string", "enum": ["subtitle_captions","headline_overlays","kinetic_typography","app_ui_labels","infographic_labels","mixed_overlays","emoji_text_hybrid","none"] },
"video_production": { "type": "string", "enum": ["UGC_handheld","studio_directed","screen_recording_live","app_mockup_animated","graphic_animation_only","mixed_live_and_graphic","mixed_UGC_and_screen","stock_footage_produced","AI_generated_video","documentary_cinematic","slideshow_static_frames","screencast_tutorial","talking_head_produced","animated_explainer"] },
"video_subject": { "type": "string", "enum": ["presenter_talking_head","presenter_with_product","presenter_lifestyle_scene","hands_only_POV","app_screen_walkthrough","product_hero_rotating","before_after_sequence","transformation_reveal","animated_character_scene","voiceover_with_broll","infographic_sequence","social_feed_scroll","multi_person_compilation","environment_establishing","text_kinetic_sequence","reaction_overlay_scene"] },
"format": { "type": "string", "enum": ["video_under_6s","video_6_15s","video_15_30s","video_30_60s","video_over_60s"] },
"emotional_tone": { "type": "string", "enum": ["aspirational","fear_based","humorous_playful","educational_informative","urgent_FOMO","calm_trust","provocative_edgy","empathetic_relatable","luxurious_premium","nostalgic","inspirational_motivational","casual_conversational"] },
"copy_structure": { "type": "string", "enum": ["headline_only","headline_plus_subtext","long_form_story","minimal_no_text","bullet_benefits","story_arc_narrative","question_answer","listicle_numbered","social_proof_quote","data_driven_stats"] },
"offer_framing": { "type": "string", "enum": ["price_anchor","free_trial","percentage_discount","dollar_discount","BOGO","limited_time_urgency","scarcity","value_stack","money_back_guarantee","free_shipping","bundle_deal","subscription_savings","no_offer_brand_only","comparison_pricing","pay_what_you_want"] },
"cta_type": { "type": "string", "enum": ["learn_more","shop_now","try_free","get_started","download","sign_up","subscribe","buy_now","book_now","get_offer","claim_deal","see_more","send_message","watch_more","swipe_up","custom"] },
"cta_custom_text": { "type": "string" },
"cta_source": { "type": "string", "enum": ["on_screen_text","transcript","title","caption","body","description","inferred"] },
"key_claims": { "type": "array", "items": { "type": "string" }, "minItems": 2, "maxItems": 5 },
"social_proof_type": { "type": "string", "enum": ["none","user_quote","star_rating","user_count","award","celebrity"] },
"color_palette": { "type": "array", "items": { "type": "string", "pattern": "^#[0-9A-Fa-f]{6}$" }, "minItems": 2, "maxItems": 3 },
"has_human_face": { "type": "boolean" },
"text_to_visual_ratio": { "type": "string", "enum": ["text_heavy","balanced","visual_dominant","no_text"] },
"video_pacing": { "type": "string", "enum": ["single_shot","slow_cinematic","medium","fast_cuts","rapid_montage"] },
"audio_style": { "type": "string", "enum": ["dialogue","voiceover","music_only","silent","mixed"] }
},
"required": ["visual_summary","hook_type","hook_text","hook_source","narrative_arc","presenter_type","scene_structure","on_screen_text_style","video_production","video_subject","format","emotional_tone","copy_structure","offer_framing","cta_type","cta_source","key_claims","social_proof_type","has_human_face","text_to_visual_ratio","video_pacing","audio_style"],
"if": { "properties": { "cta_type": { "const": "custom" } }, "required": ["cta_type"] },
"then": { "required": ["cta_custom_text"] },
"additionalProperties": false
}
```
(Full field descriptions are in the taxonomy above; the team's original spec also carries a worked example for a coin-scanner app: hands-only POV, curiosity gap hook "Can I buy a house? 🏠🤔", multi-segment compiled arc, mixed live and graphic production.)
---
## Reference L. Static ad creative analysis standard
Moved to `lyra-copy-competitor-static` (Reference L there, the team's full static standard with field descriptions and the worked example).
lyra-copy-competitor-static75.2 KB
View saved version →
---
name: lyra-copy-competitor-static
description: "Copy a competitor's static ad (one image, a carousel, several statics, or a key frame of their video) for a mobile app in Lyra. Analyses the reference in the team's static creative analysis standard (Claude's own look at the image, or Lyra's Creative Analysis node), takes every fact from the user's Brand Kit, offers a close remake and a free adaptation with variations, writes the new layout, text and Nano Banana Pro prompt, then generates the new static and its variants. Use for \"copy this competitor static\", \"make a banner like this one\", \"remake this image ad for my app\", \"do this carousel for us\", \"analyse this static and make ours\", \"a static from this competitor video\", a Meta Ad Library screenshot, or several competitor statics to learn from. Core image rules come from lyra-static-image-generation."
---
# lyra-copy-competitor-static
Image mini skill. Takes a static ad that works for someone else, finds out **why** it works, and rebuilds that mechanism as a new static for the user's app: their pain, their feature, their person, their words, their brand. Six jobs in order:
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
1. **Analyse** the reference (Step 1a): the team's static standard (Reference L) plus a production breakdown with the layout map.
2. **Go to the Brand Kit** (Step 1b) and take every fact from it.
3. **Ask the user** how to retell the reference: close remake, free adaptation, or both, with 2 to 3 variations (Step 1c).
4. **Write the new static** (Step 2): transfer map, new texts, side by side, concept card.
5. **Write the new prompt** (Step 2): zone by zone, for Nano Banana Pro.
6. **Generate** the static in Lyra, then offer variants (sizes, languages, persona, headline, animation).
**The Brand Kit is never skipped.** Remake or adaptation, the new static always gets its name, audience, pain, feature, person, words, claims, offer, colors and CTA from the user's Brand Kit (and the user's words in this chat). The reference gives only the mechanism.
**Brand Kit at every step.** The kit is not one step at the start; it is checked at every step:
| Step | What the Brand Kit decides |
|---|---|
| 1. Context | which kit (chat → the workflow's kit → the workspace's kits → ask); `assign_brand_kit` on the workflow so every Lyra node works with it |
| 1a. Analysis | nothing yet: the teardown describes only the reference, so their facts never mix with ours; the kit comes right after |
| 1b. Brand Kit sheet | every field read and written down; gaps marked as hypotheses to confirm |
| 1c. Questions | every mode and variation told with the kit's name, audience, pain, feature and offer |
| 2. Transfer map | every cell in the "Ours" column has its **kit source** (the field, or "user, in chat"); no source → it doesn't go into the ad |
| 2. New texts | tone of voice, customer words, approved claims; forbidden claims and must exclude checked line by line |
| 2. Prompt | palette (kit hex), type style (kit fonts), logo, icon and screenshots from the kit's assets, positioning → polish level, must include |
| 4. Build | the kit assigned to the workflow (and to every Lyra variation made for a variant) |
| 8. Quality | trace check: every word, number, color, claim and asset on the static traced to the kit or the user |
| Variants | other segments, markets and languages come from the kit |
**This is a way of thinking, not a script.** The rules below are defaults and good practice. Use judgment: when a different layout, subject or line serves the user's app better, do it and say why in one line. Fixed: the line between mechanism and identity (next section), truth (no invented claims, reviews or numbers; the competitor's claims are never ours), the Brand Kit's facts, UI fidelity (the user's screenshots, exactly), Lyra's technical limits, and the user's explicit choices.
**Base skill first.** Everything not written here follows `lyra-static-image-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, concept card and layout map, on-image text, realism, styles, models (Reference A), layout library (B), styles (C), realism toolkit (D), persona (E), edits and swaps (F), UI and logo (G), sizes and languages (H), errors (I), de-slop (J), Meta statics (K), Brand Kit (L). This file only adds what is specific to copying a static reference. If the two disagree, the user wins, then this file, then the base skill.
**Other skills for their parts.**
- The reference is a **video** and the user wants a video → `lyra-copy-competitor-ad`. A static from a competitor video is built here (Step 1a, static from a video).
- The app's UI in the static, store screenshot sets → `lyra-ui-motion-video` (UI fidelity, phone shot, store rules).
- A persona or a world built for the audience → realism and casting from `lyra-ugc-video`; versions for other segments → `lyra-audience-variations` (its layers and one-story test apply to statics, built with the edit patterns of the base skill).
- Headline lines: the line checks, awareness levels and hook base of `lyra-video-hooks` apply to a static headline (it is the hook of a static).
- New angles on the copied concept → `lyra-ad-concept-multiplier`. Other sizes and languages → `lyra-adapt-image`. An animated version → `lyra-ui-motion-video` (UI-led) or `lyra-video-ad-generation`.
---
## What we copy, what we never copy (hard)
A competitor's static is a **proof that a mechanism works on this audience**, not material to reuse. We copy the mechanism, never the identity.
| Copy (the mechanism) | Never copy (the identity) |
|---|---|
| the concept and the angle (the bet the ad makes on the audience) | their brand name, app name, logo, icon, slogan, catchphrases |
| the hook mechanism (`hook_type`: a question, a stat, a before/after, a self-blame line) and the headline's job and shape | their exact headline, subline, labels, chat lines, CTA text (rewritten every time) |
| the composition and the layout map: zones, their order, their rough shares of the frame, the reading order | their photo, illustration, 3D render or any part of their image: never traced, cropped, outpainted or used as a reference for generation by default |
| the text hierarchy and the word budget per block | their people: faces, look; no lookalike; their mascot or characters |
| the type of visual subject (a chat, a result card, a person in the pain moment, a split before/after) | their UI, screens and features (ours come only from our screenshots) |
| the production level (`visual_production`: UGC raw, vector, 3D, collage) | their claims, numbers, ratings, reviews, awards, offer and price |
| the CTA position and type, the offer slot (filled only from our kit) | their palette and trade dress as a whole look; a distinctive typeface; their exact illustration style |
**Rewrite test for every text block.** A block keeps its **job** (callout, question, reframe, proof row, CTA) and may keep its **shape** (a question in the user's voice, three short sentences, "here's your…" + a plan), but its words are new and built from the Brand Kit. No line of ours shares a run of about five words with theirs, unless it is an ordinary phrase anyone would say ("try it free"). If a line only works with their product, it doesn't go in.
**Look test for the whole static.** Put both side by side at phone size (or as thumbnails). Would a viewer think ours is theirs, or made by them? Then too close: change the subject, the palette, the illustration style, the type or the lines until the answer is no. The layout mechanism can be the same; the ad must look like the user's brand.
---
## Two modes: close remake or free adaptation
Both are offered by default (Step 1c); the user picks one or both. **Both run as an A/B on one teardown when the user wants**: same app card, one remake, one adaptation, named so the media buyer sees which is which. Both are built on the Brand Kit.
| | **A. Close remake** | **B. Free adaptation** |
|---|---|---|
| What stays | the same composition and zones in the same order, zone shares within about ±5% of the frame, the same text hierarchy and number of blocks, word count per block within about ±20%, the same type of visual subject, the same production level, the same CTA position and type | the idea, the angle, the hook mechanism, the reading order; everything else is redesigned for the brand |
| What changes | the app name, pain, feature, person or subject, words, palette, type, UI, CTA, offer (all from the Brand Kit) | everything the remake changes, plus the composition, the subject, the production style (often a native phone-real photo for cold traffic), the number of blocks, a layout from the base layout library if one fits better |
| Pick it when | the reference is a proven winner (running a long time, often 60 days or more in Meta Ad Library), the same audience and category, and the mechanism fits the app truthfully | a different audience, category or positioning; the mechanism depends on something the user doesn't have; the reference's look clashes with the brand; or the user wants "the idea, not a copy" |
| Risk | too close to the competitor (run the look test) | losing what made it work (keep the hook mechanism and the reading order) |
| Test value | isolates execution: "does this format work for us too?" | tests the concept in our own voice and look |
---
## Step 1 additions: the reference and the request
1. **The reference.** Ask for it if missing. Accepted sources:
- **an image file** in the chat, in a connected folder, or a public direct link to the file. JPEG, PNG, WebP. The clean ad image beats a screenshot of the whole feed (small text gets unreadable);
- **a Meta Ad Library, TikTok or Instagram page link**: a web page, not a file, so it can't be fetched. Ask the user for a screenshot or the downloaded image. Don't retry the page link;
- **a carousel**: every card, in order, each as its own image;
- **several statics** for one idea (3 to 5 of the same competitor, or several competitors in the category): all of them, with which one runs longest if known;
- **a competitor video** to make a static from: the video file (MP4, WebM, MOV) or screenshots of the frames the user likes (Step 1a, static from a video).
Check `list_uploads` first: the user may have uploaded it already in Lyra.
2. **Why this ad.** In the same message, one line each, all optional: what do you like in it (the layout, the headline, the chat, the look)? How long has it been running; a known winner? Whose ad is it (their app name stays out of everything)? The ad copy, if they have it (title, caption, body, description from Meta Ad Library): it only fills gaps the image doesn't show.
**Signals of a winner in Meta Ad Library** (signals, not proof): still active after 30 to 60 days or more · the same concept in several versions from the same advertiser (sizes, languages, headlines, people), which usually means it is being scaled · used across several placements. A new ad with no history is a hypothesis, not a proven mechanism: say so, and lean to mode B.
3. **The request.** What the user wants changed or kept ("same but for students", "in Portuguese", "as a carousel", "our mascot instead of a person", "9:16 for Stories"). The user's request wins over the reference.
**Defaults (state, don't ask):** both modes offered, Claude recommends one · the same ratio and placement as the reference (4:5 Feed if unknown; 9:16 when it's a Stories or Reels static; 1:1 when the reference is square) · English, or the language the user asks for · **Nano Banana Pro** for every final, 2K (4K when the static carries small text, a UI screen or a close-up face) · count 2 per concept (the user picks) · the reference **analysed only**, never connected to generation · competitor's name only inside the "Reference teardown" note · variants offered after the first results (After the copy).
**Recommended first run:** A. Finals first (the base skill's option A), remake and adaptation side by side when both were picked. The analysis runs before the plan and costs no credits on Path 2.
---
## Step 1a: analyse the reference
The result is always one **teardown** with two layers, saved in the user text node "Reference teardown":
- **Layer 1, creative classification:** one JSON object in the team's static ad analysis standard (Reference L at the end of this file; the same standard as Lyra's "Ad creative analysis (image)" prompt). It says what the ad **is**, in fixed categories the team can compare across many ads.
- **Layer 2, production breakdown:** what Claude needs to **rebuild** it: the layout map with zone shares, text hierarchy and word counts, subject, style, the bet, why it works, the don't copy list. Layer 1 alone isn't enough for a remake.
### Order of evidence
- **The image is the source of truth.** Ad copy (title, caption, body, description) only fills gaps not visible on the image and never overrides what the image shows.
- Every field rests on evidence. Nothing is invented: a gap in layer 2 is written "not readable" or "not visible"; in layer 1 the source field says `inferred` where the schema allows it.
- Look at the whole image before classifying: the visible headline or hook text, the layout and spatial composition, the main objects, subjects or characters, UI elements, lists, panels, charts, the CTA button, the amount of text against imagery.
### Path 2: Claude's own analysis (default for statics)
Claude can see images, so this is the default and costs no credits.
- **The file is in Claude's environment** (attached in the chat, or staged from a connected folder): open it and look at it directly.
- **Small text:** crop and enlarge the zone before transcribing (a short script, for example PIL: `img.crop((x0,y0,x1,y1)).resize((w*3,h*3))`), or ask the user for a sharper original. Never guess a word: write "not readable" and ask.
- **Zone shares:** measure the zones in pixels (top and bottom of each block divided by the image height), so the layout map has real numbers, not impressions.
- **Colors:** the 2 to 3 dominant colors as hex from the pixels, most dominant first (a short script: downscale, k-means with 3 to 5 clusters, sort by pixel count, drop near-duplicates).
- **No file, only a description:** ask for the image. A static can't be copied from a description.
### Path 1: Lyra's Creative Analysis node
Lyra's analysis node, **Creative Analysis** (action `pattern_import`), can take an image. The MCP tools can **run** and **read** it, but can't **create** it.
1. `get_workflow` on the user's workflow: a Creative Analysis node on the canvas → connect the uploaded reference to it if it isn't (`connect_nodes`), read its price next to Run, say it, run it after a yes, read the output.
2. No such node → don't wait: Path 2. Mention once that the user can add an Upload Image and a Creative Analysis node if they want Lyra's own breakdown next to Claude's.
3. **Output already in the standard** (Reference L) → becomes layer 1 after a check: exact property names, exact enum values, all required fields, `visual_summary` first, `cta_custom_text` when `cta_type` is `custom`, 2 to 5 `key_claims` in the claim format, 2 to 3 hex colors, no extra properties. **Output in another shape** (Lyra's Creative Anatomy: Source, Structure, Message, Execution, Concept Summary) → map it into the standard; fill what it doesn't say from Path 2.
4. The node's output is a source, not the new static. The rewrite is still written by Claude, by this file's rules, from the Brand Kit.
### Layer 1: creative classification (JSON)
Written exactly by Reference L: one valid JSON object, the schema matched literally (exact names, exact enums, no additional properties, all required fields), `visual_summary` first, `key_claims` in the format `"[exact element from creative] — [why it works / what it communicates]"`, `cta_custom_text` when `cta_type` is `custom`, `color_palette` 2 to 3 hex codes. In a pipeline that expects the raw object, return only the JSON, nothing before or after it. In this skill the JSON goes into the "Reference teardown" note, and the user gets a short readable version in Step 1c.
### Layer 2: static production breakdown (template)
Short, factual, one line per field, in the same note under the JSON:
1. **Header:** platform and placement · ratio and pixel size · single image or carousel (number of cards) · whose ad (internal only) · how long it has run, if known.
2. **The bet (one line):** "They bet [audience] will [action] because [concept] addresses [pain] through [mechanism]." This is what we copy.
3. **Layout map** (the heart of a static copy), top to bottom and left to right:
| Zone | From → to (% of height) | What is in it | Exact text | Type: weight, size feel, case, color | Notes |
|---|---|---|---|---|---|
| 1 | 0 → 22% | chat: user bubble right, app bubble left | "…" / "…" | rounded sans, regular, white on grey / on pink | bubbles stylised, not iOS |
4. **Reading order:** what the eye reads first, second, third (and why: size, contrast, position, a face).
5. **Text hierarchy and budget:** each block (hook, headline, subline, rows, CTA) with its word count; total words; share of the frame covered by text.
6. **Visual elements:** the hero (person, mascot, product, phone, chat, table, result) · props · background · light and camera if it's a photo (phone-real or camera-real, lens feel, light source).
7. **Style:** `visual_production` in words, palette, typography style, level of polish, what makes it look native or designed.
8. **The app in the ad:** UI shown or not, which screen, phone or flat card, the result shown, how much of the frame.
9. **CTA and offer:** button text, shape, color, position; offer if any.
10. **Their claims** (from `key_claims` and anything else on the image), listed so we never reuse them.
11. **Why it works:** 2 to 3 short reasons.
12. **Don't copy list:** the identity of this ad by name (their app name, mascot, slogan, illustration style, photo, palette, typeface, exact layout trade dress).
13. **Can't be reproduced truthfully:** what depends on something the user doesn't have (a real review, a rating, a personalised number, a feature, a physical product, a celebrity) and the nearest truthful version.
### Carousels
- **Layer 1 per card:** one JSON per card (the standard reads one image), `format: "carousel"` on each, in the card order.
- **Layer 2 for the set**, plus a **card list:** # · role (hook, problem, feature, proof, offer, CTA) · main visual · exact text · what carries over between cards (the shared anchors: background, type, persona, frame).
- What makes the set work: card 1 is the hook and must stand alone; the swipe promise ("3 reasons…", a story to finish); the last card closes with the CTA. These are mechanism; copy them.
- Remake: the same number of cards and the same role per card. Adaptation: the number may change (2 to 10), the arc stays.
### Several references
1. One teardown per reference (layer 1 and a short layer 2 each), labelled R1, R2, R3.
2. A **pattern sheet** (user text node "Pattern sheet"): the layer 1 fields they share (that shared part is the mechanism the category bets on), what varies between them, which one runs longest. Example: "all three: `hook_type: question`, `composition: chat_ui_layout`, `visual_production: illustration_vector`, CTA as a custom plan button; varies: mascot, palette, offer".
3. The copy is built on the pattern: usually mode B (the shared mechanism in our own execution), or mode A of the strongest single reference. Say which, in one line.
4. Never stitch elements of several competitors into one ad (a headline from R1, a layout from R2, a mascot from R3): that copies three identities. Take the shared mechanism, execute it once in the brand's look.
### Static from a competitor video
When the user wants a static from a competitor's video ad (to test the same concept across placements):
1. **Frames:** with the video file in Claude's environment and ffmpeg: frames every 1 s, plus about 2 per second in the first 3 s (`ffmpeg -i ref.mp4 -vf "fps=1,scale=1080:-1" frames/%03d.png`); without a shell, ask the user for screenshots of the moments they like (at least the first frame, the proof moment, the end card).
2. **Pick the key frame with the user:** usually the hook frame (the first frame, the thumbnail), the proof moment (the result on screen, the reaction), or the end card. Recommend one in one line.
3. **Analyse the key frame with Reference L** (`format: "static_image"`), plus a one-line summary of the video's arc in layer 2, so the static keeps the video's bet. The full video teardown, if the user wants a video too, is `lyra-copy-competitor-ad`.
4. A frame is not a static ad yet: it usually has no headline and no CTA. The copy adds the headline (the video's hook line, rewritten as on-image text, 2 to 8 words) and a CTA from the kit, in clean zones.
---
## Step 1b: the Brand Kit (always, in both modes)
Right after the teardown, before a single line is rewritten. The reference says **how** the static works, the Brand Kit says **what** the new static is about and **who** it talks to. Nothing is taken from the competitor's brand, and nothing is invented to fill a gap.
**Which Brand Kit** (base Reference L):
1. A Brand Kit given in the chat → use it.
2. Otherwise `get_workflow` (the kit assigned to the workflow) and `list_brand_kits` (the kits in the workspace).
3. **Exactly one** candidate → confirm in one line: "I'll make it for {kit name}, right?"
4. **More than one** → ask which, with their names. Never mix two kits in one ad.
5. **None** → ask once: send it here, or should I check and connect one of the workspace's kits? Or type the essentials: app name, what it does, audience, pains, the feature to show, approved claims, forbidden claims, offer, tone, colors (hex), logo, icon and screenshots.
6. Once chosen, `assign_brand_kit` on the workflow if it isn't assigned yet.
**Brand Kit sheet** (top of the "Transfer map" note), one line per field: app name exactly as written · what it does · audience and segments · pains in their words · desires · objections · features (mark the one that answers the reference's pain) · approved claims and proof (real reviews, real ratings, real numbers) · forbidden claims · offer and CTA · tone of voice · positioning (sets the polish level) · colors (hex) and fonts · mascot, if the brand has one · assets (logo, icon, screenshots, product photos, store badges) · markets and languages · must include / must exclude.
**Gaps.** A missing pain → 3 to 5 pain hypotheses in the audience's words, to confirm. Missing screenshots → no screen in the static, or ask for them. No approved claim → no claim. No real review → no review card. No mascot → a persona, an object or an original spot illustration, never a mascot invented to look like theirs. A gap is never filled from the competitor's ad.
**Conflicts.** The user's words win over the kit; name the conflict in one line. If the reference's mechanism clashes with the kit (a meme template for a premium finance brand, a body before/after for a health app, a must exclude), say so and propose the version that keeps the mechanism inside the brand's rules.
## Step 1c: ask the user, and offer variations
One message, after the teardown and the Brand Kit sheet, before any build. Every option is written with the Brand Kit's real name, audience, pain, feature and offer, so the user sees their own static.
1. **The reference in 3 to 4 lines:** the bet, the hook (`hook_type`, the hook text), the layout and look (`composition`, `visual_subject`, `visual_production`), why it works (`key_claims`). Several references: the shared pattern.
2. **The two modes**, told in Brand Kit terms, one recommended:
- **A. Close remake:** "the same layout zone by zone, but it's {app name}: {pain from the kit}, {feature}, {subject}, {CTA}, in your colors."
- **B. Free adaptation:** "the same idea and hook, retold for {audience} in {tone}, as {another subject or production style}, ending on {CTA}."
- **Both as an A/B** (one remake + one adaptation from the same teardown).
3. **2 to 3 variations**, one line each, each built on the Brand Kit, one recommended. Ways to vary (pick what fits):
- another pain or segment from the kit (the same layout for "students" and for "night-shift nurses");
- another subject (a person in the pain moment instead of a mascot, the real app screen instead of a chat, a result card);
- another production level (vector → phone-real photo for cold traffic, raw → elevated for premium);
- another headline angle on the same layout (question → statement → stat from the kit);
- another layout from the base layout library with the same bet;
- another medium: the static as a short animated version (first frame of a video), or a carousel of the same concept.
4. **The CTA and the app.** Unless the reference already carries it in a way that fits: the CTA button with the kit's offer, the real app screen (from a screenshot), the logo or icon small in a corner, or no logo (most native statics don't need one). Ask which.
5. **Only the questions still open**, in the same message: missing kit fields, screenshots, language, ratio, number of cards.
Each variation the user picks becomes its own concept (`C1`, `C2`…) with its own transfer map and node; more takes of one concept are `count`, not new nodes (base rule).
**Example (short, fictional app Calmly, reference R1 = the fasting chat static in Reference L).**
> Reference: a pink vector static, a chat where the user asks "Why does nothing work for me?" and the app answers warmly, then a plan headline, a personal stats row and a green plan button. It works because the self-blame question is the viewer's own thought, and the answer removes the blame.
> Brand Kit: Calmly, the only kit in this workspace. Make it for Calmly, right?
> A. Close remake: the same chat layout, but it's Calmly: "Why can't I switch off at night?" answered by "Because your brain never gets a wind-down.", then "here's your 5-MINUTE WIND-DOWN", a row with the real texts of your timer screen, a violet button "START TONIGHT". Navy, violet and cream, our own small moon illustration instead of their raccoon.
> B. Free adaptation: the same question and warm answer as two stylised bubbles over a phone-real photo of Mia, 21, awake in bed at 2 am; CTA "Try it tonight".
> Variations: V1 both as an A/B (recommended: proven layout plus a native photo version) · V2 the remake for the kit's second segment, night-shift nurses ("Why can't I sleep after a shift?") · V3 the adaptation as a 3-card carousel (question → the timer screen → CTA).
> Open: the timer screenshot (for the row and V3), and 4:5 Feed or 9:16 Stories?
---
## Step 2 addition: transfer map, new texts, new prompt
### The transfer map
Before writing a line, map each part of the reference to the user's app, for the mode and variation picked. The "Ours" column comes **only** from the Brand Kit sheet and the user's words. One row per zone and per element: **reference → ours · keep / translate / drop · why**. It goes into the "Transfer map" text node.
| Element | Reference | Ours (from the Brand Kit) | Kit source | Action |
|---|---|---|---|---|
| Bet | dieters who failed will try because a warm answer removes self-blame | students who can't switch off will try because a warm answer says it's not their fault | audience, pains (segment 1) | translate |
| Zone 1 (0 → 22%): chat | "Why does nothing work for me?" / "Because you never gave your body a break." | "Why can't I switch off at night?" / "Because your brain never gets a wind-down." | pains, customer words; tone | translate (same job: self-blame question, warm reframe) |
| Zone 2 (22 → 55%): mascot | raccoon with a tea cup | small original illustration: a crescent moon asleep on a pillow, in Calmly's palette | none needed (original element in kit palette) | translate (their mascot never kept) |
| Zone 3 (55 → 70%): headline | "here's your FASTING START" | "here's your 5-MINUTE WIND-DOWN" | feature: wind-down timer; screenshot 2 | translate (shape kept: lowercase lead + caps plan name) |
| Zone 4 (70 → 80%): stats row | Height, Weight, Goal (personalised numbers) | "Tonight's plan · 5 min · Lights off" (the real texts of the timer screenshot) | screenshot 2 (timer screen) | translate (no personal numbers: Calmly doesn't ask for them) |
| Zone 5 (80 → 86%): tagline | "Same foods. Different timing. Different results." | "Same bed. Same night. Five calm minutes." | tone of voice | translate (rhythm kept, no claim) |
| Zone 6 (86 → 100%): CTA | green button "CALCULATE YOUR PLAN" | violet #8B7CF6 button "START TONIGHT" | offer and CTA; colors | translate |
| Claim | fasting results | none approved → no result claim | approved claims: none | drop |
| Palette | #F5D7D1 pink, #2ECC71 green, #1A1A1A | #1B1F3B navy, #8B7CF6 violet, #F4F1EA cream | colors | translate |
| Style | flat vector, pastel, warm | flat vector, the same polish level, Calmly's palette, rounded type | positioning (mass, calm) | keep level, change look |
**Rules for the map:**
- Every zone of the reference has a row. A zone we drop is written as dropped, with the reason.
- Every "Ours" cell names its **kit source** (a Brand Kit field, an uploaded asset, or "user, in chat"). A cell without a source is either confirmed with the user or left out.
- Their pain becomes the **closest real pain** in the user's pain map, in the audience's words. None is close → the mechanism doesn't transfer: say so, offer mode B or another reference.
- Their feature becomes **one real feature** of the user's app. Never borrow a feature the app doesn't have.
- **Personalisation, data rows, results, ratings:** only what the app really does and really shows. A stats row is kept only if the app really builds something from those inputs, filled with an example that is clearly an example or with the texts of a real screenshot; never a number that reads as a claim.
- Their claims are dropped by default; a claim comes back only if the Brand Kit has its own approved one.
- Their person becomes a persona from the user's audience (base Reference E, `lyra-ugc-video` casting), different in look from theirs. Their mascot becomes the kit's own mascot, an original spot illustration, a persona or an object.
- Their palette and look become the brand's palette at the same polish level.
### The new texts
Written by Claude, from the transfer map, into the "Transfer map" note under the map:
- **Word budget per block.** Remake: each block within about ±20% of the reference's word count, the same number of blocks. Adaptation: the base skill's budget (headline 2 to 8 words, subline ≤ 10, CTA 1 to 4, up to 3 blocks), unless the format needs rows (chat, list, stats).
- **Same job, new words.** Each block keeps its job and may keep its shape; the words come from the Brand Kit and customer words. Run the rewrite test on every block.
- **The headline is the hook.** Write it with the line checks of `lyra-video-hooks` (one idea, simple, specific to this app and moment, true). The picture and the headline say one idea together (base Concept and layout).
- **Another language:** the texts written in that language by Claude, not translated word for word; check length against the zone (translations run longer).
- **Side by side**, part of the concept the user approves:
| Zone | Reference (what it does) | Ours (what it shows and says) | Words ref / ours | Kept | Changed |
|---|---|---|---|---|---|
### The concept card
As in the base skill (Concept and layout), one per concept, written from the transfer map: hypothesis in one line · visual · **layout map top to bottom with each zone's share and every text in quotes** · style · palette · text total. Plus: mode (A or B), reference code (R1), Brand Kit used. The concept the user approves has: the Brand Kit, the mode and variation, the transfer map in short, the side by side, the concept card, the plan table and the model question (base Step 2).
### Writing the new prompt
The prompt is built **from our layout map, never from their image**. The model never sees the competitor's static.
**Field → prompt part:**
| From the teardown | Goes into the prompt as |
|---|---|
| `composition` + layer 2 layout map | "Layout from top to bottom:" each zone with its share of the frame, what is in it and its exact new text in quotes |
| `visual_production` | the style line: phone-real or camera-real photo (base Realism), or the illustration style described fully (line, fill, texture, palette, proportions), or the collage, infographic or type-only look |
| `visual_subject` | the hero: our persona (character card), our product shot, our real screen, our stylised chat, our result card |
| `hook_type`, `hook_text` | the headline's job and shape, with our text in quotes |
| `copy_structure`, `text_to_visual_ratio` | the number of text blocks, their hierarchy, the share of the frame for text |
| `cta_type`, `cta_source` | the CTA button: position, shape, color (brand hex), our text in quotes |
| `color_palette` | replaced by the Brand Kit hex codes |
| `has_human_face` | a persona with a face or no face, as in the reference (remake), or by choice (adaptation) |
| `format: carousel` | one node per card, shared anchors word for word |
**Prompt order** (base Prompt rules, static ad): format and ratio in words → each connected input's job ("[Image1] is the app logo", "[Image2] is the app screen") → the scene or the illustrated world → **the layout from top to bottom**, zone by zone, with shares and every text in quotes, type style, color, size feel → the screen "exactly as supplied" + its key texts, if any → palette (hex) → style line → "The only text in the image is …" → a short "Avoid …" line. 100 to 220 words; non-negotiables early.
**Never in a copy prompt:** "like the reference", "in the style of [competitor]", their app name, their mascot's description, their slogan, their exact lines, their hex codes, their typeface name.
**Pattern: close remake, vector chat layout (Nano Banana Pro, 4:5).**
> Static app ad, vertical 4:5, flat vector illustration style with soft shapes and gentle grain. [Image1] is the app screen: its texts are used only as labels below. Background: cream #F4F1EA. Layout from top to bottom: top 22%: two stylised rounded chat bubbles, generic, not any real messenger: on the right a grey bubble with dark text "Why can't I switch off at night?", on the left a navy #1B1F3B bubble with white text "Because your brain never gets a wind-down." · 22 to 55%: centered, a small original illustration of a crescent moon asleep on a soft pillow, navy and violet, rounded shapes, no face details beyond closed eyes · 55 to 70%: headline in two lines, centered: "here's your" in a light rounded sans, then "5-MINUTE WIND-DOWN" in a heavy rounded sans, navy, very large · 70 to 80%: one row of three small rounded pills with dark text: "Tonight's plan", "5 min", "Lights off" · 80 to 86%: small centered line "Same bed. Same night. Five calm minutes." · bottom 14%: a wide rounded button in violet #8B7CF6 with white bold text "START TONIGHT". Generous margins, about 5% on every side. The only text in the image is the two bubbles, the headline, the three pills, the small line and the button. Avoid: extra text, logos, real messenger UI, gradients, clutter.
**Pattern: free adaptation, phone-real photo (Nano Banana Pro, 4:5).**
> Static app ad, vertical 4:5, UGC phone-photo style. Mia, 21, light brown skin, freckles, dark curly hair in a loose bun, oversized grey hoodie, lies awake on her side in a dark bedroom at 2 am, phone light on her tired face, looking past the camera. Shot on a 24mm phone camera, deep focus, warm bedside lamp from the right, natural skin texture, visible pores, slight dark circles, rumpled grey duvet, a charger cable on the nightstand. Layout from top to bottom: top 25%, over the dark wall: two stylised rounded chat bubbles, generic, not any real messenger: right, a white bubble "Why can't I switch off at night?"; left, a violet #8B7CF6 bubble with white text "Because your brain never gets a wind-down." · middle: Mia · bottom 15%: a rounded button "Try it tonight" in violet #8B7CF6 with white text, centered. The only text in the image is the two bubbles and the button. Avoid: beauty filter, studio lighting, extra text, logos, real app interfaces.
### Optional: a layout wireframe for a close remake
When a remake's layout keeps drifting (zones in the wrong place, wrong proportions), give the model the layout as an image without any of the competitor's identity: Claude draws a **neutral wireframe** in its environment (grey boxes for the zones at the measured shares, a white background, labels like "HEADLINE", "CHAT", "BUTTON", no colors, no text from the reference, no shapes from their image), uploads it (`create_upload` + `attach_upload`) and connects it with its job stated first: "[Image3] is a layout wireframe only: place the zones where its grey boxes are; do not copy its grey color, its labels or any text from it." Check the result for label leaks ("HEADLINE" printed in the image) and drop the wireframe if it leaks.
---
## Best way to build it
The format of the reference decides the build. The user's explicit choices override any row. Models and prices: base Reference A.
| If the reference is | Graph | Models |
|---|---|---|
| **Single static (default)** | Brand Kit assigned → uploads the static needs (logo, icon, screenshots) → one Image Generation node per concept (remake, adaptation), the reference's ratio, 2K (4K for small text, UI or a close face), count 2 → the user checks every letter | nano-banana-pro |
| A person in the pain moment (`person_*`) | persona node first when the person appears in several statics (count 2, the user picks), connected as reference; otherwise the person described in the ad prompt | nano-banana-pro |
| The app's UI (`app_screen_demo`, `screenshot_UI`) | our screenshots uploaded → the screen "exactly as supplied" in the prompt + key texts; a separate phone-shot node when the screen is the hero (base Reference G, `lyra-ui-motion-video`) | nano-banana-pro |
| A chat, a comment, a social post (`text_message_chat`, `social_post_embed`) | stylised generic bubbles or post frame, our texts in quotes; never a copy of iOS, WhatsApp, Instagram or system UI; a fictional chat never presented as real | nano-banana-pro |
| A review card, a rating, a user count (`review_quote_card`, social proof) | only a real review, rating or number from the Brand Kit, attributed; none → the slot becomes a demo or a result from a real screen | nano-banana-pro |
| A mascot (`character_mascot`) | the kit's own mascot uploaded as reference; no mascot → a persona, an object or an original spot illustration; never a lookalike of theirs | nano-banana-pro |
| Illustration or 3D (`illustration_*`, `AI_art_stylized`) | the same style family, described fully in words, in our palette; Flux 2 or Wan 2.7 Pro only as a second look to compare | nano-banana-pro |
| Type-only or text-heavy (`text_only`, `infographic_data`) | Pro first; a block that keeps failing → Ideogram 3.0 Quality test, or a clean zone for the designer | nano-banana-pro · ideogram-v3-quality |
| A meme format (`meme_template`) | only an original or free format (a lo-fi caption over our own scene); never a copyrighted meme image or a known meme character | nano-banana-pro |
| **Carousel** | one node per card, the shared anchors (palette, type, persona, background, frame) word for word in every prompt; persona or style reference shared; card 1 = hook, last card = CTA | nano-banana-pro |
| Several references | pattern sheet → one concept per picked direction (usually the shared mechanism in mode B, plus a mode A of the strongest) | nano-banana-pro |
| A key frame of a competitor video | the frame analysed (Step 1a) → our static built like a single static, headline and CTA added in clean zones | nano-banana-pro |
| Many directions, tight budget | drafts on nano-banana-2 at 1K, count 2 to 3 → the user picks → winners rerun on Pro (base row) | nano-banana-2 → nano-banana-pro |
**Plan example** (base Step 2 table, the Calmly example, both modes):
| # | Node label | Node · model · key settings | Inputs (role) | Stage |
|---|---|---|---|---|
| 1 | Ref R1: chat fasting static (analysis only) | upload image | — | — |
| 2 | Reference teardown | user text | — | — |
| 3 | Transfer map (Brand Kit sheet, texts, side by side) | user text | — | — |
| 4 | Concept cards C1 remake, C2 adapt | user text | — | — |
| 5 | Screenshot: timer | upload image | — | 1 |
| 6 | Ad C1: remake · chat wind-down · 4:5 | image · google/nano-banana-pro · 4:5 · 2K · count 2 | 5 (screen texts) | 2 |
| 7 | Ad C2: adapt · Mia 2 am chat · 4:5 | image · google/nano-banana-pro · 4:5 · 2K · count 2 | — | 2 |
| 8 | C1 · 9:16 + 1:1 (after approval) | image resize · google/nano-banana-2 | 6 | 3 |
Node 1 is connected to nothing; nodes 2 to 4 are notes for the user and feed nothing.
**The reference in the workflow.** The competitor's image is uploaded into Section "Reference" for the record and analysis (and for Path 1), labelled "Ref R1: chat fasting static (analysis only)", and **never connected to an image generation node**. A competitor image as a generation reference leaks their mascot, palette, type and text into ours; the layout comes from our layout map in words (and, if needed, from a neutral wireframe).
**Layout.** Section "Reference" (uploaded reference, Creative Analysis node if any, "Reference teardown", "Pattern sheet", "Transfer map" notes; nothing here feeds generation) → then the base layout: Sources (concept cards, uploads) → Persona / product → Ads → Sizes and languages. Labels: "Ad C1: remake · chat wind-down · 4:5", "Ad C2: adapt · Mia 2 am chat · 4:5", "Card 2: timer screen · 4:5".
## Run options (copy)
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes, per option. The analysis comes first and on its own: **Path 2** costs no credits · **Path 1** costs what the Creative Analysis node shows next to Run (say it before running). Then: **A. Finals first (recommended):** every concept on Nano Banana Pro, count 2 · **B. Drafts first:** Nano Banana 2, 1K, count 2 to 3, winners rerun on Pro · **C. Everything:** ads → sizes → languages (count 1, no pause to pick). Remake and adaptation together: the same options, both concepts.
---
## After the copy: variants
The user asked for variants right away, so when the first results are approved, offer 2 to 4 next steps in one message, each with what it changes, what stays, which skill builds it and its credits. Change **one variable per variant** and list what is held constant (Lyra's Ad Variation rule), so each variant is a clean test:
| Variant | What changes | How it's built |
|---|---|---|
| **Headline** | the headline (another angle on the same pain: question → statement → a stat from the kit) | an edit node on the approved static: "Change only the headline to '…'; keep everything else exactly"; or a new node with the same prompt and only the headline replaced |
| **Persona or world** | the person, their wardrobe, the room, a prop, the time of day, for another segment from the kit | the edit patterns of the base skill (Reference F: person swap, world swap), the layers and the one-story test of `lyra-audience-variations` |
| **Subject or production level** | mascot ↔ persona ↔ real screen; vector ↔ phone-real photo | a new node (a new concept), same layout map |
| **Remake ↔ adaptation** | the other mode on the same teardown | a new node |
| **Sizes** | 9:16, 1:1, 4:5 | `lyra-adapt-image`: Image Resize for simple layouts, a Pro recompose node when text or the hero must move (recompose, don't crop) |
| **Languages** | the texts in another language | `lyra-adapt-image`: Image Translation for statics without UI; with UI → the localized app's screenshots + texts written in that language, a new Pro node |
| **New angle** | the argument of the ad, same concept | `lyra-ad-concept-multiplier` |
| **Animated version** | the static becomes the first frame of a short video | `lyra-ui-motion-video` (UI-led) or `lyra-video-ad-generation` |
Variants of an approved static live in the same workflow (one node per variant, next to the original, labelled with its code) or, for a whole new version of the canvas, in a Lyra variation (`create_variation` copied from the original; the original stays Main as the control). Never overwrite the approved static.
---
## Prompt rules (copy static)
| Node | Write | Avoid |
|---|---|---|
| Reference teardown (text) | layer 1: one JSON object by Reference L (per card for a carousel); layer 2: the production breakdown with the measured layout map; facts only, gaps marked "not readable" / "not visible" | guesses; enum values not in the schema; paraphrased claims; long praise of the ad |
| Pattern sheet (text) | shared fields across references, what varies, which runs longest, the mechanism in one line | elements stitched from several competitors |
| Transfer map (text) | Brand Kit sheet; one row per zone and element: reference → ours → keep / translate / drop → why; the new texts with word counts; the side by side | their lines copied in as "ours"; their claims, numbers or offer |
| Concept card (text) | as the base skill, plus mode, reference code and Brand Kit | prompts meant for the model |
| Static ad (image) | the base static ad prompt, with the layout from our map, zone shares and every text in quotes; inputs with stated jobs; "The only text in the image is …" | "like the reference"; their name, mascot, lines, palette, typeface; a competitor image connected; generated logos, badges, UI |
| Carousel card (image) | the shared anchors word for word → this card's role and zones → its text | a different palette, type or persona per card |
| Edit for a variant (image) | verb first, keep list, one change (base Reference F) | two changes at once; re-describing the whole static |
| Layout wireframe (upload) | grey boxes at the measured shares, neutral labels, its job stated first in the prompt | any color, shape or text from the competitor's image |
Every prompt is self-contained (base rule): describe the static itself, never "like the reference".
---
## Truth, rights and brand safety
- The competitor's static is a reference for analysis. Their image, illustration, photo, mascot, text and logo are never part of our ad, and never a generation reference.
- No competitor name, logo or product in our ad, and no comparison with them by name. A comparative ad that names a competitor is a legal question for the user's team, not a default; this is not legal advice.
- Their claims, numbers, ratings, reviews, user counts and awards are theirs. Ours come only from the Brand Kit or the user. Review cards and ratings only real and attributed; personalised data only as the app really produces it.
- No lookalike of their person, no copy of their mascot or characters, no copyrighted meme images or known meme characters, no copies of iOS, WhatsApp, Instagram or system UI (stylised bubbles and cards only).
- Formats and layouts are free to use; a specific illustration, photo or trade dress isn't. When in doubt, move further from the reference (mode B).
- AI people are creative scenes, never real customers (base Truth and disclosure); remind the user once, in the final report, about the platform's AI label for photoreal synthetic people.
- **Brand safety** (Lyra's System Preamble): no profanity, no political statements, no unsubstantiated health claims, no digs at the competitor even without its name. The Brand Kit's **forbidden claims are enforced absolutely**, in every headline, bubble, row, card and CTA, even when the reference makes that claim; if the user asks for one, say once that it is on the kit's forbidden list and leave it out unless the user confirms the kit is outdated. No body before/after for health or weight-loss apps, even if the reference has one.
---
## Deliverable and naming
1. Section "Reference": the uploaded reference(s) (analysis only), "Reference teardown" (one per reference), "Pattern sheet" (several references), "Transfer map" with the Brand Kit sheet, the new texts and the side by side.
2. A "Concept card" per concept.
3. All planned uploads, persona or product shots, the new statics (remake and/or adaptation), carousel cards, and the variants the user picked.
Name every final with a code the media buyer can paste into Ads Manager: `B{batch}-A:{angle}-F:CopyStatic-{visual_subject}-{Remake|Adapt}-R{reference}-C{concept}-{ratio}`, e.g. `B5-A:CantSwitchOff-F:CopyStatic-Chat-Remake-R1-C1-4x5`. Carousels add `-Card{n}`; variants `-V{n}{what changed}` (`-V2Headline`, `-V3Persona`); other languages `-{lang}`. Several references: `R1+R2` when the concept comes from the pattern. The competitor's name stays out of the code; `R1` points to the teardown note.
---
## Common mistakes (copy static)
| Mistake | Prevention |
|---|---|
| Prompt written before the reference is understood | Teardown first, then the Brand Kit, then the questions, then the map, then the prompt |
| Brand Kit skipped "because it's a close remake" | Step 1b in both modes; every name, pain, feature, claim, offer and color from the kit |
| Several kits, one picked silently or two mixed | Ask which kit; one kit per ad |
| Gaps in the kit filled from the competitor's static | Pain hypotheses, no screen, no claim, no review card |
| Modes asked as an abstract choice | Both modes and 2 to 3 variations told with the kit's real name, audience, pain and offer |
| Layout described by impression ("text at the top") | Measured zone shares in the layout map, copied into the prompt |
| Small text guessed | Crop and enlarge, or ask for a sharper original; "not readable" |
| Enums invented, claims paraphrased, ad copy overriding the image | Reference L exactly; the image first; ad copy only for gaps |
| A carousel analysed as one image | One JSON per card + the card list |
| Elements stitched from several competitors | Pattern sheet; the shared mechanism executed once in our look |
| The competitor's image connected to the generation node | Analysis only; layout in words, a neutral wireframe if needed |
| "Like the reference" or their name in a prompt | Self-contained prompt from our layout map |
| Their headline lightly reworded | Same job, new words; rewrite test on every block |
| Their mascot redrawn, their palette and typeface kept | Our mascot, persona or object; brand palette; look test at thumbnail size |
| Their stats row, rating or review reused with our name | Real data from the kit only; otherwise the slot becomes a real screen or a result |
| Fake chat presented as a real conversation, iOS or WhatsApp look copied | Stylised generic bubbles; fictional, never claimed as real |
| Copyrighted meme image or known meme character | Original format only |
| Static from a video with no headline or CTA | Add the hook line as on-image text and the kit's CTA in clean zones |
| Remake drifts (zones moved, three extra lines) | Zone shares ±5%, block count and word counts kept; wireframe if it keeps drifting |
| Adaptation loses the hook mechanism | Keep the bet, the hook mechanism and the reading order |
| Text not checked letter by letter | Base rule: every word with the user; a failing block → clean zone for the designer |
| Variants changing several things at once | One variable per variant, held-constant list |
| Competitor's name in the node label or the final's code | Teardown note only; `R{n}` in the code |
| Page link from Ad Library retried as a file | Ask for the image or a screenshot |
## Quality gates (copy static)
- **Stage 0 (teardown, Brand Kit, map, texts, prompt; Claude checks before sending):** the Brand Kit chosen and confirmed? Its sheet filled, gaps marked? Mode, variation and CTA picked by the user, told in the kit's terms? Layer 1 a valid JSON object by Reference L (exact names and enums, all required fields, `visual_summary` first, claims in the claim format, per card for carousels)? Layer 2 filled, the layout map measured? The bet in one line? Every zone mapped (keep, translate, drop), every "Ours" cell with its kit source? Pain and feature real for our app? Their claims dropped? Every block passes the rewrite test? Word counts fit (remake ±20%, adaptation the base budget)? Don't copy list written? The prompt self-contained, built from our map, no competitor image connected?
- **Stage 1 (sources: persona, product, phone shot):** the base Stage 1 checks; our persona clearly not their person; the screen identical to our screenshot word by word.
- **Stage 2 (the statics), side by side with the reference at phone size:** the same mechanism lands in half a second (remake: the same reading order and zones; adaptation: the same bet)? Every letter and number identical to the transfer map, nothing extra? Our palette, our subject, our type; nothing that still says "competitor" (a phrase, a mascot, a color, an illustration style)? Clear in one look what **our** app does? CTA from the kit? Trace check: every word, number, color and asset traced to the kit or the user, nothing from the forbidden list? Ratio and safe zones right? Plus the base Stage 2 checks (light, hands, logo, realism or style).
- **Stage 3 (variants, sizes, languages):** only the intended variable changed? Nothing cropped, headline and CTA in the safe zones, texts re-checked in every language, named with codes? AI label reminder given?
## After the test
A static that wins for a competitor is a hypothesis for us, not a promise: judge ours by our own KPIs (cost per result for the goal: trial, payer; CTR alone proves nothing; enough conversions before calling a winner). Say what won: the mechanism (the copy works → more on this bet: headline variants, personas, sizes, languages, an animated version) or not (the mechanism doesn't transfer to our audience → note it, try the other mode or another reference). Statics fatigue fast at scale (often 7 to 14 days): plan the next round. Save the teardown, the transfer map and the result to the project's creative repository, so the next copy starts from what the team already learned.
---
## Reference L. Static ad creative analysis standard (layer 1)
The team's standard for classifying a static ad (the same as Lyra's "Ad creative analysis (image)" system prompt). Claude follows it word for word for layer 1 of every static teardown, and checks the Creative Analysis node's output against it.
**Role and objective.** A performance marketing creative analyst for STATIC ads: extract structured classification data from the IMAGE (primary source of truth) and ad copy text fields (secondary support only). Operational priority: return exactly one valid JSON object, follow the schema exactly, and keep outputs strictly limited to evidence supported by the provided creative inputs and the classification rules below.
**Inputs.** One image plus optional ad copy text fields: title, caption, body, description.
**Core requirements.** Respond only with valid JSON · no preamble, markdown backticks or explanation · exactly one JSON object that conforms to the schema · no text before or after the JSON object · match the schema literally: exact property names, exact enum values, no additional properties · `visual_summary` always the first field in the output object.
**Critical priority rule.** The IMAGE is the source of truth · use title, caption, body ONLY to fill gaps not visible in the image · if information is visible on the image, do NOT override it with title, caption or body.
**Visual analysis: what to examine.** Before classifying any field, examine the image carefully: visible headline or hook text on the image · layout and spatial composition · main objects, subjects or characters · presence of UI elements, lists, panels, charts or graphics · presence of CTA buttons or action prompts · amount of on-image text vs imagery.
**Rules for `visual_summary`.** Describe what is shown and how the message is visualized: a concrete visual-mechanical description, not a generic marketing summary. Name specific visual elements and their arrangement ("coins lined up with prices next to each", "ranking list layout", "phone UI screenshot", "big headline + small subtext", "CTA button on bottom") · if there is a demonstrated action or implied interaction, name it ("scan", "tap", "compare", "before/after") · transcribe any key on-image text exactly · avoid generic phrasing like "encourages users to…" unless combined with the concrete visual mechanic.
**Rules for `key_claims`.** For each claim: (1) quote or closely reference the **exact language, phrase or visual element** present in the creative, never paraphrase, never invent; (2) explain the **rhetorical mechanism**: how this specific language or visual choice communicates value or overcomes resistance. Format: `"[exact element from creative] — [explanation of why this works / what it communicates]"`. If a visual element (not text) is doing the persuasion work, describe what is shown and why it functions as a claim. Never include claims not present in the image.
### Taxonomy
**`hook_type`** (the primary persuasion mechanic of the opening): `problem_solution` opens by naming a pain point, then frames product as the fix · `before_after` shows or implies a state change, improvement or transformation · `social_proof` leads with others' behavior, ratings or adoption as the hook · `UGC_testimonial` first-person user voice or real person sharing their experience · `curiosity_gap` withholds information to create a knowledge gap that demands resolution · `fear_urgency` triggers anxiety, loss aversion or threat of missing out · `question` opens with a direct question aimed at the target audience · `statistic_claim` leads with a specific number, percentage or data point · `POV_first_person` places viewer in the scenario using "you" or first-person perspective · `tutorial_how_to` opens with a promise to show how to do something · `unboxing_reveal` sequential discovery or unwrapping as the hook mechanic · `comparison_vs` directly contrasts two options, brands or states · `transformation` focuses on the journey or change process, not just the endpoint · `day_in_life` follows a character through a scenario to create identification · `GRWM_get_ready` get-ready-with-me structure, product integrated into a routine · `reaction` someone's visible emotional reaction to a product or situation · `myth_busting` opens by challenging a common belief or assumption · `listicle` numbered or bulleted list format as the primary structure · `controversy_hot_take` provocative or polarizing opening designed to stop the scroll · `authority_expert` credentials, expertise or professional context as the opening signal · `emotional_story` narrative with emotional arc as the primary hook · `product_demo` product shown in use or in action as the immediate hook · `challenge` invites viewer to participate in or attempt something.
**`hook_source`** (where the hook text was found): `on_screen_text` text visible directly on the image · `visual_description` hook is conveyed through the visual itself, no text · `title` from the ad title/headline metadata field · `caption` from the ad caption metadata field · `body` from the ad body copy metadata field · `description` from the ad description metadata field · `inferred` hook inferred from overall creative intent, no explicit source.
**`offer_framing`** (how the economic proposition is framed): `price_anchor` shows a high reference price to make the actual price feel cheap · `free_trial` leads with a no-cost trial period · `percentage_discount` discount expressed as a percentage off · `dollar_discount` discount expressed as a specific dollar/currency amount · `BOGO` buy one get one or similar quantity deal · `limited_time_urgency` offer is available only for a restricted time window · `scarcity` limited quantity or availability drives action · `value_stack` lists multiple inclusions to make total value feel large · `money_back_guarantee` reduces risk by promising a refund · `free_shipping` removes delivery cost as a conversion barrier · `bundle_deal` multiple products packaged together at a combined price · `subscription_savings` frames recurring billing as cheaper than alternative · `no_offer_brand_only` no economic proposition present, pure brand or product message · `comparison_pricing` shows competitor price alongside own price · `pay_what_you_want` user controls the price within a range.
**`cta_type`** (the call to action type): `learn_more` directs to more information, low commitment · `shop_now` direct purchase intent · `try_free` free trial or no-cost start · `get_started` onboarding or activation, often for apps or SaaS · `download` app or file download · `sign_up` account creation or registration · `subscribe` ongoing subscription commitment · `buy_now` immediate purchase, higher urgency than shop_now · `book_now` appointment or reservation · `get_offer` claim a specific deal or promotion · `claim_deal` similar to get_offer, deal-focused · `see_more` expand content or view additional items · `send_message` opens a chat or messaging flow · `watch_more` video content continuation · `swipe_up` story-format upward swipe action · `custom` any CTA text not covered by the above; extract exact text into `cta_custom_text`.
**`cta_source`** (where the CTA was found): `on_screen_text` CTA button or text visible on the image · `title` · `caption` · `body` · `description` (the ad copy metadata fields) · `inferred` no explicit CTA visible; inferred from landing intent.
**`visual_production`** (how the image was created, its source): `studio_photo` professional photography, controlled lighting, clean or neutral background · `lifestyle_photo` professional photo in a real-world context (home, street, gym, outdoors) · `UGC_raw` shot on a phone, unpolished, authentic feel, non-directed · `stock_photo` recognizable stock aesthetic, clearly not proprietary or brand-specific content · `AI_photo_realistic` AI-generated image that is photorealistic; may not be immediately obvious · `AI_art_stylized` AI-generated art that is visibly stylized and does not pretend to be a photo · `illustration_vector` flat or clean vector illustration style, digital · `illustration_hand` hand-drawn or painterly style, sketchy or expressive · `illustration_3d` 3D render of objects, characters or scenes · `screenshot_UI` actual screenshot of an app interface, website or digital product · `collage_mixed` combination of photo + graphics + text layered together in one frame · `infographic_data` data visualization, charts or tables as the primary visual element · `text_only` pure typography with no imagery at all · `meme_template` a recognizable internet meme format adapted for the ad.
**`visual_subject`** (the primary object or subject shown): `person_selfie` self-shot angle, close framing, camera below eye level · `person_talking_head` person faces camera, upper body visible, direct address to viewer · `person_lifestyle_action` person in context doing something relevant to the product · `person_transformation` human before/after change shown (weight, skin, appearance) · `product_hero_clean` product shown alone, isolated, nothing else in frame · `product_in_use` product being used by hands or shown in an environment · `product_transformation` result generated by the product shown (room redesign, photo edit, output) · `app_screen_demo` app UI shown as the primary content, not merely as a compositional element · `before_after_split` two states shown simultaneously side by side or top/bottom · `data_table_list` rows of data, attributes, scores or comparison table as hero element · `character_mascot` illustrated or animated character as the dominant visual element · `environment_scene` a place, room or setting with no person as the focus · `text_message_chat` simulated chat, DM, SMS or notification UI as the main visual · `social_post_embed` a fake or real social media post shown as a visual element · `review_quote_card` a testimonial or review as the visual centerpiece · `result_proof` outcome shown as the hero: score, stat, before/after metric, transformation result.
**`composition`** (spatial layout structure): `single_hero` one dominant element centered or prominently placed, everything else is secondary · `split_screen` two distinct panels dividing the frame (left/right or top/bottom) · `collage_grid` multiple images or elements arranged in a grid or mosaic · `editorial_layered` overlapping elements, magazine or poster style, asymmetric · `full_bleed_text` image fills the entire frame with text overlaid on top · `data_table_layout` structured rows and columns dominate the layout · `chat_ui_layout` layout mimics a messaging or chat interface with bubbles and replies.
**`format`**: `static_image` a single non-moving image · `carousel` multiple swipeable image cards.
**`emotional_tone`** (the dominant emotional register): `aspirational` projects an idealized future state the viewer wants to reach · `fear_based` triggers anxiety, threat or loss aversion · `humorous_playful` uses comedy, wit or lightheartedness · `educational_informative` calm, factual, teaches something without emotional pressure · `urgent_FOMO` creates pressure to act now or miss out · `calm_trust` measured, reassuring, builds confidence and credibility · `provocative_edgy` intentionally provocative, boundary-pushing or controversial · `empathetic_relatable` mirrors the viewer's feelings or situation without judgment · `luxurious_premium` signals exclusivity, quality and high status · `nostalgic` evokes warmth or longing for the past · `inspirational_motivational` motivates action through positivity and empowerment · `casual_conversational` friendly, low-pressure, feels like a message from a peer.
**`copy_structure`** (how the text on the image is structured): `headline_only` a single dominant text element, nothing else · `headline_plus_subtext` main headline supported by one or more lines of secondary text · `long_form_story` extended paragraph or narrative text block · `minimal_no_text` no text or only a logo/brand mark · `bullet_benefits` unordered list of features or benefits · `story_arc_narrative` text tells a mini story with a beginning, middle and resolution · `question_answer` question posed then answered within the same creative · `listicle_numbered` numbered list format as the primary copy structure · `social_proof_quote` a quote from a user, expert or third party as the primary copy · `data_driven_stats` statistics or data points as the primary copy element.
**`social_proof_type`** (type of social proof present, even as a secondary element): `none` no social proof of any kind present · `user_quote` a direct quote from a real or simulated user · `star_rating` numerical star rating or review score shown · `user_count` number of users, downloads, customers or reviews displayed · `award` third-party award, badge, certification or "App of the Year" type signal · `celebrity` a known public figure, influencer or verified creator featured.
**`text_to_visual_ratio`** (balance between text and imagery): `text_heavy` text dominates the frame; imagery is minimal or absent · `balanced` text and imagery occupy roughly equal visual weight · `visual_dominant` imagery dominates; text is minimal (logo, short CTA, or none) · `no_text` no text present anywhere in the image.
Plus: **`color_palette`** 2 to 3 dominant colors as hex codes, ordered most dominant to least · **`has_human_face`** true if a human face is visible anywhere in the image · **`key_claims`** 2 to 5 claims, each `"[exact element from creative] — [rhetorical mechanism explanation]"`, based only on what is visible in the image, never invented · **`hook_text`** exact text of the hook as it appears on the image, or the closest description if visual-only (used for pattern matching) · **`cta_custom_text`** required when `cta_type` is `custom`: the exact CTA text as it appears.
### Schema
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Static Ad Creative Analysis",
"type": "object",
"properties": {
"visual_summary": {
"type": "string",
"description": "Concrete visual-mechanical description of the creative. First field in output. Describe what is shown, how it is arranged, what text is visible on the image, and how the message is visualized. Transcribe key on-image text exactly."
},
"hook_type": {
"type": "string",
"enum": ["problem_solution","before_after","social_proof","UGC_testimonial","curiosity_gap","fear_urgency","question","statistic_claim","POV_first_person","tutorial_how_to","unboxing_reveal","comparison_vs","transformation","day_in_life","GRWM_get_ready","reaction","myth_busting","listicle","controversy_hot_take","authority_expert","emotional_story","product_demo","challenge"]
},
"hook_text": {
"type": "string",
"description": "Exact text of the hook as it appears on the image, or closest description if visual-only. Used for pattern matching."
},
"hook_source": {
"type": "string",
"enum": ["on_screen_text","visual_description","title","caption","body","description","inferred"]
},
"offer_framing": {
"type": "string",
"enum": ["price_anchor","free_trial","percentage_discount","dollar_discount","BOGO","limited_time_urgency","scarcity","value_stack","money_back_guarantee","free_shipping","bundle_deal","subscription_savings","no_offer_brand_only","comparison_pricing","pay_what_you_want"]
},
"cta_type": {
"type": "string",
"enum": ["learn_more","shop_now","try_free","get_started","download","sign_up","subscribe","buy_now","book_now","get_offer","claim_deal","see_more","send_message","watch_more","swipe_up","custom"]
},
"cta_custom_text": {
"type": "string",
"description": "Required when cta_type is 'custom'. Exact CTA text as it appears."
},
"cta_source": {
"type": "string",
"enum": ["on_screen_text","title","caption","body","description","inferred"]
},
"visual_production": {
"type": "string",
"enum": ["studio_photo","lifestyle_photo","UGC_raw","stock_photo","AI_photo_realistic","AI_art_stylized","illustration_vector","illustration_hand","illustration_3d","screenshot_UI","collage_mixed","infographic_data","text_only","meme_template"]
},
"visual_subject": {
"type": "string",
"enum": ["person_selfie","person_talking_head","person_lifestyle_action","person_transformation","product_hero_clean","product_in_use","product_transformation","app_screen_demo","before_after_split","data_table_list","character_mascot","environment_scene","text_message_chat","social_post_embed","review_quote_card","result_proof"]
},
"composition": {
"type": "string",
"enum": ["single_hero","split_screen","collage_grid","editorial_layered","full_bleed_text","data_table_layout","chat_ui_layout"]
},
"format": {
"type": "string",
"enum": ["static_image","carousel"]
},
"emotional_tone": {
"type": "string",
"enum": ["aspirational","fear_based","humorous_playful","educational_informative","urgent_FOMO","calm_trust","provocative_edgy","empathetic_relatable","luxurious_premium","nostalgic","inspirational_motivational","casual_conversational"]
},
"copy_structure": {
"type": "string",
"enum": ["headline_only","headline_plus_subtext","long_form_story","minimal_no_text","bullet_benefits","story_arc_narrative","question_answer","listicle_numbered","social_proof_quote","data_driven_stats"]
},
"key_claims": {
"type": "array",
"description": "2–5 claims. Each item: '[exact element from creative] — [rhetorical mechanism explanation]'. Base only on what is visible in the image. Never invent.",
"items": { "type": "string" },
"minItems": 2,
"maxItems": 5
},
"social_proof_type": {
"type": "string",
"enum": ["none","user_quote","star_rating","user_count","award","celebrity"]
},
"color_palette": {
"type": "array",
"description": "2–3 dominant colors as hex codes, ordered most dominant to least.",
"items": { "type": "string", "pattern": "^#[0-9A-Fa-f]{6}$" },
"minItems": 2,
"maxItems": 3
},
"has_human_face": {
"type": "boolean",
"description": "True if a human face is visible anywhere in the image."
},
"text_to_visual_ratio": {
"type": "string",
"enum": ["text_heavy","balanced","visual_dominant","no_text"]
}
},
"required": ["visual_summary","hook_type","hook_text","hook_source","offer_framing","cta_type","cta_source","visual_production","visual_subject","composition","format","emotional_tone","copy_structure","key_claims","social_proof_type","has_human_face","text_to_visual_ratio"],
"if": {
"properties": { "cta_type": { "const": "custom" } },
"required": ["cta_type"]
},
"then": {
"required": ["cta_custom_text"]
},
"additionalProperties": false
}
```
### Example output
```json
{
"visual_summary": "Pink background with a centered illustrated raccoon mascot holding a tea cup. Top section shows a simulated chat exchange — user message 'Why does nothing work for me?' answered by app bubble 'Because you never gave your body a break.' Below that: bold headline 'here's your FASTING START', a user stats row showing Height 5'6'', Weight 205 lbs, Goal 175 lbs, then the tagline 'Same foods. Different timing. Different results.' in small text. Bottom: bright green CTA button 'CALCULATE YOUR PLAN'. Dense but warm — pastel color keeps the hard weight-loss data from feeling clinical.",
"hook_type": "question",
"hook_text": "Why does nothing work for me?",
"hook_source": "on_screen_text",
"offer_framing": "no_offer_brand_only",
"cta_type": "custom",
"cta_custom_text": "CALCULATE YOUR PLAN",
"cta_source": "on_screen_text",
"visual_production": "illustration_vector",
"visual_subject": "text_message_chat",
"composition": "chat_ui_layout",
"format": "static_image",
"emotional_tone": "empathetic_relatable",
"copy_structure": "headline_plus_subtext",
"key_claims": [
"'Why does nothing work for me?' as the opening — borrows the user's own internal monologue as hook. Self-blame framing creates instant recognition before the ad reframes it.",
"'Because you never gave your body a break' — the app answers the user's question in a warm, non-judgmental tone. Positions the product as a coach that explains failure, not judges it.",
"'Same foods. Different timing. Different results.' — classic blame reframe: your choices weren't wrong, your system was. Removes willpower from the equation, lowers resistance to trying again.",
"Height / Weight / Goal stats row — fake personalization showing specific user data signals 'this plan is built for you specifically', even in a static ad with no real input."
],
"social_proof_type": "none",
"color_palette": ["#F5D7D1", "#2ECC71", "#1A1A1A"],
"has_human_face": false,
"text_to_visual_ratio": "balanced"
}
```
**How the copy of this ad goes** (worked through in Step 1c and Step 2): the chat mechanism (the user's self-blame question, the app's warm answer), the plan headline, the row and the plan button stay as a structure; the raccoon, the pink and green palette, every line and the fasting claim don't. The stats row is the one element that is "fake personalization" in their ad: ours keeps the slot only with the texts of a real screen (or a real personalised output, if the app has one), never invented personal numbers.
lyra-fix31.5 KB
View saved version →
---
name: lyra-fix
description: "Fix one part of a finished Lyra video or image ad without rebuilding it. Finds the node where the problem is born, changes only what was asked by editing the finished image on Nano Banana Pro instead of generating it again (for video: the fixed image, then the clip generated again from it), compares the new result with the old one so nothing else moved, reruns only what depends on it (image → clip → Video Editor), renders again and reports the new video or image, the workflow link and the credits the fix cost. Use for \"regenerate scene 3\", \"change her sweater\", \"another ending\", \"she has six fingers\", \"the logo is warped\", \"the screen text is wrong\", \"redo banner C2\", \"fix the headline on card 4\", \"louder music\", \"go back to the old one\", or a problem found by lyra-result-check. Not for another story, person, angle, audience, size or language (those are variations, handled by their own skills). Core rules come from lyra-video-ad-generation and lyra-static-image-generation."
---
# lyra-fix
Repair skill for every Lyra creative, video and image. The creative skills build the ad; this one fixes a part of it after it exists. It works the same way on a scene in a video ad, a card in a carousel and a banner in a static set: find where the problem is born, change that one thing, check that nothing else moved, rerun only what depends on it, put the new piece back, report.
**The goal.** The user says what is wrong in their own words ("she has six fingers in scene 3") and gets back the same ad with only that fixed, the price named before anything runs, and the old version still there to go back to.
**The one thing to understand.** Changing one word in a prompt and running the node again does **not** change one thing. It makes a new take: Lyra's models have no fixed seed, so the face, pose, light and framing come out different too. Only an **edit of the finished image** (the old image connected to a new Nano Banana Pro node, "change only…") keeps everything else. So a fix of one element is an edit of the image, not a rerun; in a video, the clip is then generated again from the fixed image, so the look stays and the motion is a new take. A rerun of the original prompt is for problems where a new take is fine or wanted (a glitch in the whole frame, a bad composition, the user asks for "another one").
**Core rules come from the base skills.** Part 1 of `lyra-video-ad-generation` (video) or `lyra-static-image-generation` (images) holds the shared steps: pre-run check, credits, picking a result, links, open canvas, runtime failures, base prompt rules. The Video Editor, captions and on-screen text follow `lyra-video-editor`. Canvas changes (a new edit node, an insert, a renamed label) follow `lyra-workflow-layout`.
**This is a way of thinking, not a script.** Fixed: change only what was asked, edit the result instead of regenerating it, fix at the source, compare old and new before calling it fixed, the cost in the same question, never an unchanged rerun, the old results kept, the right links.
---
## Fix or variation (hard line)
A fix keeps the ad and changes a detail. When the request changes what the ad *is*, it is a variation and goes to its skill. Say so in one line and hand over; don't stretch a fix into a remake.
| Request | It is | Goes to |
|---|---|---|
| A glitch: fingers, hands, face drift, morphing, flicker, a warped phone | fix | this skill |
| One detail in a scene or image: sweater, color, prop, light, expression, camera move, background object | fix | this skill |
| Another ending of the same story (another last shot, another CTA moment) | fix | this skill |
| Wrong text: a letter in the headline, the app name, a number, a caption, screen text not matching the screenshot | fix | this skill |
| Warped logo or icon | fix | this skill |
| Audio: music louder or softer, VO line reworded, a mispronounced app name, the music cut too early | fix | this skill |
| Edit: scene order, trims, a scene shorter or longer, captions size or position | fix (often free) | this skill + `lyra-video-editor` |
| Another person in the whole ad | variation | `lyra-audience-variations` |
| Another outfit, room or car through the whole ad, for another audience | variation | `lyra-audience-variations` |
| Another story, angle, reason, pain | variation | `lyra-ad-concept-multiplier` |
| A new opening (first 3 s) to test | variation | `lyra-video-hooks` |
| Another size or ratio | variation | `lyra-image-resize` |
| Another language or market | variation | `lyra-image-translation` (images) · `lyra-audience-variations` (video voice and language) |
**Rule of thumb:** if the fix touches more than about half of the generation nodes, or the user would call the result "a different ad", it is a variation. Unsure → ask in the same message as the plan: "This changes the person in every scene, so it's a new version rather than a fix: I'll make it as a variation with lyra-audience-variations. OK?"
---
## Step 1. Find the node
1. `get_workflow` now, not from memory. Read the labels, the edges and the Video Editor's `video_rendering_composition`.
2. Map the user's words to nodes:
- "scene 3", "the second shot", "the ending" → the node labelled with that scene; no labels → the clip in that position in the Video Editor (playback order, by `startMs`).
- "banner C2", "card 4", "the 9:16 one" → the label or the Section that names it.
- "her sweater", "the phone", "the room" → the earliest node that draws it (a character, a keyframe, a phone shot).
- "the music", "the voice", "the captions", "the text on screen" → the audio node or the Video Editor.
3. **Inside one multi-shot clip.** The base skill builds one Seedance clip with several shots by default, so "scene 3" may be a shot inside one clip, not its own node. Find the shot's time range from the script and the composition, then pick a route in Step 2 → Video.
4. **Fix at the source.** A defect shows where it is born. Walk back along the edges from the node the user named to the earliest node that has the problem:
- wrong in the keyframe or character image too → fix the image; the clip after it reruns from the fixed image;
- right in the image, wrong only in the clip (fingers merge while moving, the face drifts) → fix the clip only;
- wrong in every scene with this person (the sweater everywhere) → every node that draws it, with the same words (Step 2 → One element in several nodes); many nodes → maybe a variation (above).
Claude can see images and videos only with a browser signed in to Lyra or after `lyra-result-check`. Without either, ask in one line: "Is it already wrong in the image 'Scene 3: kitchen', or only in the video?"
5. Several problems at once → collect them all into one fix round: one plan, one cost, one rerun of the shared nodes after them (one Video Editor render, not three).
---
## Step 2. The change
**Change only what was asked.** The picked results of the other nodes stay picked. In every prompt that stays, the anchors (character, place, style, phone), the user's own words, settings, references and frames stay word for word.
**Edit or new take.** Two ways to change a result, and they keep different things. Pick per problem and say which in the plan:
| | Edit of the result | New take |
|---|---|---|
| How | a new image node on Nano Banana Pro with the finished image connected, "change only…"; for video, the clip is then generated again from the fixed image | the same node, prompt or setting changed, run again |
| What stays | everything except the element: face, pose, framing, light (in a video the look; the motion is a new take) | the anchors in the prompt; face, pose, light and framing can shift |
| Use for | one element: sweater, prop, color, a hand, text, an object in the background | a glitch in the whole frame, a bad composition, another ending, "give me another one" |
**Cheapest fix first.** Go down the list and stop at the first that does the job:
| # | Fix | Cost |
|---|---|---|
| 1 | Another result that already exists (count 2, an earlier run): pin it (base Step 7) | 0 |
| 2 | A Video Editor change (`lyra-video-editor`): order, trims, a clip's own sound muted, music volume, speed, freeze frame, captions text, size and position, on-screen text, a logo or screenshot laid over a broken moment | 0 |
| 3 | A settings change on one node (duration, resolution, a reference's job, a frame instead of a reference where the model allows it) | that node's rerun |
| 4 | An image edit on Nano Banana Pro (Images below) | one image (+ the clip after it) |
| 5 | A clip generated again from the fixed image, or an insert clip for one shot (Video below) | one clip or one short clip |
| 6 | A new take: prompt change on one node | that node's rerun + its dependents |
| 7 | Another model for that node (base Reference A ladder, up or down) | that node's rerun + its dependents |
### Writing the change
Find the words that cause the problem and replace only them. Add the request as concrete, renderable words, and a short constraint if it's a glitch.
- "change her sweater to a green one" → an edit: "Change only her grey hoodie to an oversized moss-green knit sweater…"; in the prompts of the nodes that stay, "grey hoodie" → "oversized moss-green knit sweater" so later reruns don't bring the grey one back.
- "six fingers" → an image edit of that hand ("Fix only her right hand: five fingers, natural anatomy, holding the mug…"), or in a new take simplify the hand action (one object, visible contact, fewer fingers in view) and add "five fingers on each hand, natural hand anatomy" to the constraints line. Never an unchanged rerun "for luck" (base rule).
- "another ending" → a new take of the ending only: rewrite the ending beat and the final frame line; the earlier beats, timing and VO stay unless the VO speaks over the ending (then the VO line too, its length checked).
- "the screen text is wrong" → base Reference G of the image skill: the screenshot connected, the fidelity line, the 3–5 key texts in quotes, a larger screen; in a video, the cheapest is often the screenshot or a phone shot laid over that moment in the Video Editor.
- In the plan show only the change: `before: "grey hoodie" → after: "oversized moss-green knit sweater"`, never the whole prompt.
### Images: the edit on Nano Banana Pro
The house way to change one element on an image. **Always Nano Banana Pro.** Never Lyra's `change_element_on_image` node (it runs on Nano Banana 2 and changes too much).
1. **A new image node** next to the source (`create_image_generation_node`), model `google/nano-banana-pro`, label "{source label} · fix: {what}" ("Scene 3: kitchen · fix: sweater").
2. **Connect the picked result of the source image** to it as a reference: it is [Image1]. Ratio `match_input_image`, resolution as the source (2K, or 4K when a screen must be read). Other references only when the change needs them (the screenshot for screen text, the logo file, the persona for a face fix).
3. **The prompt:** verb first, the one change, then the keep list in words, then "everything else exactly as in [Image1]":
> Change only her grey hoodie in [Image1] to an oversized moss-green knit sweater with a ribbed collar. Keep everything else exactly as in [Image1]: the same woman, face, hair, skin and expression, the same pose and hands, the mug, the framing and camera angle, the kitchen, the light direction and color, the phone and its screen, every text. Do not add, remove or move anything else.
4. **Run, then compare** the new image with [Image1] side by side, at full resolution (a browser signed in to Lyra: open both image files and draw them next to each other into a canvas, as in `lyra-result-check` Step 3; Lyra's files can't be downloaded into a shell). Zoom into the face and hands. Check, one by one: the change happened, and fully (the whole sweater, both sleeves) · face, hair, skin, age, expression the same · pose, hands, fingers the same · framing, crop and camera angle the same · light direction, color and shadows the same · background, props and colors the same · phone screen, logo and every text the same, letter by letter · no bleed (traces of the old sweater, a half change).
5. **Not right on the first try** (the sweater didn't change, or something else moved): run the same node once more, with what drifted named in the keep list and "change only…" kept at the start ("…keep her face exactly as in [Image1], the same eyes and nose"). Then compare **both takes with [Image1]** and pick the one where only the element changed. Pin it on every node after it (base Step 7) and say which one went on.
6. **Two takes, neither right** → change the way: a smaller change in words, the element described more concretely, a crop where the element is larger, or a new take of the image (it will look different; say so). Still failing → leave it for the designer and say exactly what.
7. **No browser to look:** say the image is ready and ask the user to compare it with the old one by the check in point 4.
8. **Several changes on one image** (the sweater and the mug): one change per edit, in a chain. Each next edit takes the **best result so far** as [Image1], not the original, or the earlier change comes back. Compare after every step. Keep the chain short (two or three edits); a longer one → a new take of the image from the fixed prompt.
**Other image cases.**
- **Rerun the original node** (a new take) only when the problem is in the whole composition, or the user wants another version.
- **Text on the image:** an edit on Pro naming the exact spelling ("Change only the headline text to 'Sleep in 5 minutes', same font, size, color and place"); after two fails leave a clean zone for the designer (image skill Reference I).
- **Children of the image.** A fixed static may have resized or translated versions made from it. List them in the plan and ask in the same question whether to redo them too, with their credits; default yes when the fix shows in them.
- **Carousel card:** edit only that card; the card keeps the Story Bible anchors word for word (`lyra-carousel`).
### Video
**The main way: fix the picture, then generate the clip again.** A clip is not edited directly. The image the clip is made from is fixed by the Nano Banana Pro edit above, compared with the old one, and then the clip is generated again from the fixed image with the same prompt. The image holds the look (person, outfit, place, light); the motion is a new take. Say so in the plan: "the look stays, the movement will be a new take".
1. **The problem is in the image the clip is made from** (the keyframe, the phone shot, the character): edit that image on Pro, compare, then generate the clip again from the fixed image: on Seedance 2.0 or Kling as the first frame (re-pointed to the new result, base Reference E), on Seedance 2.5 as the reference in place of the old one. The clip's prompt stays word for word, except the words of the change ("grey hoodie" → "moss-green knit sweater"); the same model, duration, ratio, resolution and sound settings.
2. **The problem is only in the clip** (the image is right, the clip got the sweater wrong, a background object appeared): take the frame of that shot (Lyra's `extract_frames`, an image node action, up to 10 timestamps; or the keyframe if the shot has one), edit the frame on Pro, compare, and generate the clip again from it on a frame model (Seedance 2.0, Kling) with the same prompt. Clips made from references only (Seedance 2.5): fix the element in the prompt and generate a new take with the same references; the look stays, the details of the frame can shift.
3. **A shot inside a multi-shot clip:** offer the insert in the plan, recommended for a small fix:
- **A. Insert clip (recommended):** take the shot's frame (`extract_frames`), fix it on Pro, generate a new short clip only for that shot from it (a frame model, the same anchors, the shot's length from the script), and lay it over the original in the Video Editor at the shot's time. The rest of the ad stays exactly as it is. Cheaper.
- **B. New take of the whole clip:** the fixed prompt for the whole clip. Every shot is generated again and can come out different, the good ones too. Costs the whole clip.
4. **A glitch in motion** (fingers merging while moving, morphing, a jump): a new take of that clip or an insert, with the hand action simplified and the constraint line; for continuity across the cut, start from the last frame of the clip before it (`extract_frames`) on a frame model.
5. **Text and logo in a video are cheaper in the edit.** On-screen text and captions live in the Video Editor: fix them there for free (`lyra-video-editor`), never regenerate a clip for them. A warped logo in a clip → the uploaded logo laid over that moment as an image layer, or the moment covered by the end card. Wrong phone screen text → a UI insert (base Reference D): the phone shot on Pro with the screenshot connected, laid over the moment.
**Backup: a reference video** (only when the movement itself must stay exactly: a perfect take, a long gesture, lip sync that must not change). A new video node with the finished clip connected as a reference video ([Video1]) and, when the new element must look a certain way, the fixed image as [Image1]. The model watches the old clip and generates a new one that repeats its motion, camera and timing with the one change:
> In [Video1], replace only her grey hoodie with the moss-green knit sweater from [Image1]. Keep the same person and face, the same hand movements, camera movement, timing, lighting and background exactly as in [Video1].
It is still a generation and costs a clip of the same length. Models: Seedance 2.5 (reference videos up to 30 s in total) or Seedance 2.0 (up to 15 s), same duration, ratio and resolution; Gemini Omni video for a 4–10 s piece of a clip (`reference_video_trim_start` / `_end`); Kling Video 3.0 Omni for 3–10 s clips. One change per run; small artifacts can appear next to the changed area. Offer it only as a second option in the plan, after the main way, and say it is not tested yet. *Not tested in Lyra yet (lyra-fix-test-plan F05, F08): whether a video can be connected to a video node through the tools, and how much the model keeps. If the test fails, this route is removed.*
**Talking clips (UGC, dialogue, in-clip speech).** A new take of a clip with speech makes the voice, the lips and the line again, and can bring music inside the clip back. So:
- a change off the face (outfit, background, prop) → the main way (fix the frame, new take) with the same line word for word, the same voice description and the no-music sound line (base Reference C); check the line still fits the length at a calm pace; if the voice must stay exactly, the backup reference video, and keep the original clip's sound in the Video Editor when the lips still match;
- a changed line → a new take of that clip (in-clip speech), or only the VO node (separate voiceover), then the Video Editor and the captions again.
### One element in several nodes
The sweater in three scenes, the logo on four cards: edit every node that shows it, with the same words in every prompt, in one fix round. Then compare the results with each other, not only with the old ones: the same sweater (color, knit, collar) in every scene. One of them differs → one more edit of that one, with the others as references for the element.
---
## Step 3. What reruns
Build the rerun list from the edges, not from memory: the fixed node (or the new edit node), then every node downstream of it, in run order.
| Fixed | Reruns |
|---|---|
| Character or persona image | every image and clip it feeds → Video Editor (big: check the variation line) |
| Keyframe or phone shot (edited) | the clip(s) that take it, re-pointed to the edit → Video Editor |
| Clip (new take) | Video Editor |
| Insert clip (new) | Video Editor (the insert laid in) |
| Voiceover | Video Editor (the new VO length checked against the clip) + captions |
| Music | Video Editor |
| Video Editor only | Video Editor (0 credits) |
| Static image (edited) | that image (+ its resized and translated children if agreed) |
| Carousel card | that card |
Nodes not in the list are not run. Their results stay and cost nothing. An edit node feeds the next node instead of the source: move the connection from the source to the edit (`disconnect_nodes`, `connect_nodes`), and keep the source on the canvas with its results. When the source fed the Video Editor directly, disconnect it from the Video Editor too, or its clip comes back into the edit (`lyra-video-editor` → Known behaviour).
---
## Step 4. Plan and cost: one question
One short message, one question (base Step 3), with:
1. **What I found:** the node and why there ("the fingers are already wrong in the image 'Scene 3: kitchen', so I fix the image, not only the clip").
2. **What changes and how:** the before → after words, and the route: "an edit of the image, everything else stays" or "a new take of the clip, the pose and face may shift a little".
3. **What reruns:** the list from Step 3 with each node's credits (read from `get_workflow`, base Step 6) and the total, next to the balance. A second take of an edit, if it may be needed, named with its price ("+23 if the first try changes her face").
4. For a shot inside a multi-shot clip: options A and B with their credits.
5. Variation instead of in place, if it applies (Step 5).
> Scene 3 · six fingers: the hand is already wrong in the image "Scene 3: kitchen". I edit only her right hand on Nano Banana Pro (five fingers, both hands on the mug), the rest of the image stays; then the clip reruns from it. Reruns: hand fix 23 (+23 if a second try is needed) · Clip 3 338 · Video Editor 0 = **361 credits** of your 40 120. Run it?
**Free fixes run straight away** (another existing result, a Video Editor-only change): say what you did and send the new render. Everything that costs credits waits for the yes. The yes runs the whole rerun list, including the second take of an edit named in the plan; don't ask again between stages unless the real cost is more than ~15% over (base Step 6).
---
## Step 5. In place or a variation
`update_node` keeps every result already generated, a rerun adds new results next to the old ones, and an edit is a new node next to its source. So a fix of one or two nodes is made **in place**, in the variation the user is working in: the old results stay, and the user can go back.
Make a **variation** first (base Variations: `create_variation` "{name} · fix: {what}", `switch_variation`) when: the user wants to compare old and new side by side · the fix touches many generation nodes (the character, the whole clip) · the user asks. Never edit a variation the user made for something else without saying so. Right after `create_variation`, read the Video Editor's composition and the frame pins: in a new variation the edit can come out empty or pointing to old results; rebuild it by `lyra-video-editor` before any render.
The old prompt is overwritten by an in-place new take: quote the changed words, old and new, in the report so it can be put back.
**Going back** ("go back", "the old one was better"): pin the old result again on every node after it (base Step 7), or move the connection back from the edit node to the source; put the old words back in the prompt if it was changed (`update_node`); render the Video Editor again (free). The edit node stays on the canvas with its result unless the user asks to remove it.
**Open canvas.** Before editing through the tools, ask the user to switch their tab away from the workflow (an open canvas can write its old state over the edits). With a browser under Claude's control, move the tab off the workflow yourself while editing, then open the workflow again at the end to show the result.
---
## Step 6. Run and put it back
1. **Pre-run check** (base Step 5) before every run: connections, references, frames, settings, valid nodes, inputs ready.
2. `run_node` in run order; `get_run_results` until done; never `run_node` on a running node.
3. **Compare before going on.** After an edit or a new take, look at the new result next to the old one (Step 2 → Images, point 4; for clips, frames at the same times). Only then run the nodes after it. Without a browser, ask the user to compare, or run `lyra-result-check` on that part.
4. **Pin the new result.** After a rerun the node holds old and new results. Make sure every node after it uses the new one: on video nodes set `reference_result_image_uuids` or the frame's `image_result_uuid` to the new result (base Step 7), then `get_workflow` to check it held. Then run the next node.
5. **Video Editor** (`lyra-video-editor`). Read `video_rendering_composition` first and change only what's needed:
- **the edit plays the result it was pinned to.** Each clip in the composition points to one result (`sourceNodeId`, `sourceResultUuid`, `assetUrl`). After a rerun, a new take or an edit node, the editor still plays the old clip: set the new result's `sourceNodeId`, `sourceResultUuid` and `assetUrl` (from `get_run_results`) on that clip yourself, then `get_workflow` to check;
- the new clip in its place, at the same `startMs`; a different length → adjust its `trim` or `durationMs` and the clips after it, so the ad keeps its planned length and the cuts stay where the VO expects them; `canvas.durationMs` = the end of the last clip, or the render ends on black;
- an insert clip: a node connected after the edit exists is not added on its own, so add it to the composition yourself (`assetUrl`, `sourceNodeId`, `sourceResultUuid`) as an overlay layer above the main video at the shot's `startMs`, its own sound muted if the main clip carries the sound;
- music volume under the voice, muted clip sound, captions size 80 at 75% of the height: kept exactly as they were;
- captions after a changed line: made again (`lyra-video-editor` → Captions) and checked against the new script;
- after anyone opens the editor, the 5-second check (`lyra-video-editor` → Known behaviour).
Then run the Video Editor.
6. **Failure.** A failed run → name it, one retry with a changed prompt or model and its credits (base Runtime failures).
**When to stop.** Two fix rounds on the same problem without a clean result → stop before spending again. One message: what was tried, the total spent on this fix so far, and 2–3 other ways (a simpler shot, another model, an insert or overlay in the edit, leave it for the designer, keep the best take so far). Run only on the user's pick.
---
## Step 7. Report
> Scene 3 fixed: five fingers, the rest of the ad unchanged (compared with the old frame: same face, light and pose). Video: {video url} · Workflow: https://lyra.splitmetrics.com/workflows/{uuid}. The fix cost {x} credits · balance {X}. New node "Scene 3: kitchen · fix: hand" (take 2 went on). The old image and clip are still there; say "go back" to switch.
- **Links by the base rules:** one video → the new Video Editor result + the workflow · one image → the new image + the workflow · several → the workflow only. Name the variation if the fix went into one.
- **Real spend:** balance before − after.
- **What changed,** in one line: the route, the new node or the old and new words, which take went on.
- **What was compared,** in one line (or that the user still has to compare).
- **Next step:** run `lyra-result-check` on the new render straight away (free), only on the frames of the fixed part and the cuts around it, and the sound when the fix touched it (music volume, VO, a fade). No browser and no check skill → send the check list for the fixed part (Quality gates) and ask the user to look.
---
## Common mistakes (fix)
| Mistake | Prevention |
|---|---|
| Changes one word and reruns the node, the whole image comes out different | One element = an edit of the result on Nano Banana Pro (Step 2) |
| Uses Lyra's `change_element_on_image` node | Always a new image node on Nano Banana Pro with the source connected |
| Calls it fixed without comparing with the old result | Compare face, pose, light, background, screen, text (Step 2 → Images, point 4) |
| One try, something else moved, sent anyway | A second take with the drift named, then pick the take where only the element changed |
| Rewrites the whole prompt for a one-word change | Replace only the words that cause the problem; anchors and the user's words stay |
| Fixes the clip when the defect is already in its image | Fix at the source: walk back along the edges (Step 1) |
| Reruns the whole multi-shot clip for one shot | Offer the insert clip first (Step 2 → Video) |
| Regenerates a clip for on-screen text, captions or a logo | Fix them in the Video Editor or as an overlay, for free |
| New take of a talking clip, the line or voice changes, music sneaks in | The same line word for word, the same voice, the no-music line; the reference video only when the lips must stay |
| The sweater fixed in one scene, still grey in the next | Every node that shows it, same words, compared with each other |
| Reruns nodes the fix doesn't touch | Rerun list from the edges only (Step 3) |
| Runs a paid fix before saying the price | Cost in the same question (Step 4); only free fixes run straight away |
| A separate question for the price | One message, one question |
| The next node still uses the old result | Pin the new result, or move the connection to the edit node, and check with `get_workflow` |
| A new clip of another length breaks the edit | Adjust trims and the clips after it in the composition |
| The new render still shows the old clip | Set the new result's `sourceResultUuid` and `assetUrl` on the clip in the composition |
| The insert clip is missing from the render | Add it to the composition yourself; a node connected later isn't added |
| Several changes in one edit, or each edit from the original | One change per edit, each from the best result so far |
| Captions, music volume or muted sound lost in the new render | Read the composition first, change only the clip |
| Reruns an unchanged prompt "for luck" | Change the prompt, a setting or the model; say what changed |
| Keeps spending round after round | Two rounds → stop, the total so far, other ways (Step 6) |
| Turns a new person or story into a "fix" | Fix or variation table; hand over to the variation skill |
| Grades the new result without seeing it | Look with a browser or `lyra-result-check`; otherwise ask the user with the check list |
| Three fixes, three renders | One fix round: all changes, one cost, one Video Editor run |
| "Go back" with nothing to go back to | Old results stay, edits are new nodes, old words quoted in the report |
---
## Quality gates (fix)
- **Before sending the plan (Claude checks):** the right node, at the source? Edit or new take chosen, and said what may shift? Only the asked thing changes, shown as before → after? A free route in the Video Editor checked first? The rerun list from the edges? Every node's credits, a possible second take, and the total next to the balance? A fix, not a variation? For a shot inside a clip, options A and B?
- **After each edit or new take:** compared with the old result: the change is there and complete · face, hair, pose, hands, framing, light, background, screen, logo and text the same · no bleed · the same element the same in every node that shows it.
- **After the render:** the asked thing is fixed · no new defect in the fixed part · the new piece sits in the edit at the right time, the cuts and the VO still line up · music, captions and volume as before · the planned length · the old result still there.
Pass = the user is happy with the fixed part and nothing else changed. A new problem in the fixed part → one more fix round with its cost (and the stop rule); a problem elsewhere that was already there → a separate fix, named as such.
lyra-image-resize45.8 KB
View saved version →
---
name: lyra-image-resize
description: "Adapt a finished app ad image in Lyra to other aspect ratios and ad placements (Meta Feed, Stories and Reels, TikTok, Google App campaigns, link ads, banners) without losing anything - every element, text, color and style kept, the layout recomposed for the new frame and its safe zones. Picks the build per image and ratio (Lyra's Image Resize node, a Nano Banana Pro recompose, a rebuild from the concept card, or a canvas extension or crop for the designer) and checks every element. Use for \"make this in 9:16 and 1:1\", \"resize for Stories / Reels\", \"the same banner for Feed and Stories\", \"a 1.91:1 version\", \"all sizes for Meta\", \"a full size set\", \"Google App campaign sizes\", \"a 728x90 banner from this\", or a winning static to roll out to every placement. Core image rules come from lyra-static-image-generation."
---
# lyra-image-resize
Image helper skill. Takes an image that is already approved (a static ad, carousel cards, an end card, a phone shot) and makes it fit another frame: the same ad, the same elements, the same words, the same look, **recomposed** for the new ratio and the placement's safe zones. One output per ratio, labelled and named so the media buyer can upload them as one ad with an asset per placement.
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**Resize is recomposition, not cropping.** A crop throws away part of the ad; a stretch distorts it; a centered copy on a bigger canvas wastes the frame. A good resize decides again where each element lives in the new frame, so the hero stays the hero, the headline stays readable and the CTA stays clear of the platform's buttons. So the layout for every ratio is planned **before** any credits are spent, in a Resize sheet, and only then rendered.
**Adaptation, not improvement.** The goal is the same image in a new frame, not a better one. Nothing is added, nothing is dropped, nothing is "fixed": no new text, no sharper skin, no higher contrast, no cleaner UI. That is the Image Resize node's own rule (below), and this skill holds every route to it.
**Base skill first.** Everything not written here follows `lyra-static-image-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, concept card and layout map, on-image text rules, realism, models (Reference A), layout library (B), edits and recompose (F), UI and logo (G), sizes and languages (H), errors (I), de-slop (J), Meta statics (K), Brand Kit (L). This file adds what is specific to ratios and placements. If the two disagree, the user wins, then this file, then the base skill.
**This skill takes over the resize part of `lyra-adapt-image`.** Skills that say "other sizes → `lyra-adapt-image`" mean this skill now.
**Other skills for their parts.**
- Other **languages** → `lyra-image-translation`. Order: **languages first, sizes second** (each approved language is resized; fewer runs, and a text that grew in translation is placed once per ratio).
- An image with **app UI** → UI fidelity from `lyra-ui-motion-video`: the screen in every ratio is the user's screenshot, identical word for word. App Store / Google Play **screenshot sets** have exact pixel sizes and their own rules: `lyra-ui-motion-video` (Store screenshot sets).
- **Carousels** → `lyra-carousel` (Story Bible, layout grid); this file says how a set of cards is resized together.
- The same ad for **another audience or market** → `lyra-audience-variations`; this skill changes only the frame.
- **Video sizes** (a 9:16 video for Feed 4:5 or 1:1) → the video skills: the keyframes are recomposed here, the clips are regenerated there (`lyra-video-ad-generation`, `lyra-ui-motion-video`); this skill covers only the images (keyframes, end cards, text cards).
- **Variants** of a copied competitor static → `lyra-copy-competitor-static` (After the copy), sizes built here.
**This is a way of thinking, not a script.** The rules are defaults and good practice; use judgment and say why in one line when you choose differently. Fixed: every element of the source kept, texts identical letter by letter, style and colors kept, no improvement, UI fidelity (the user's screenshots, exactly), the logo exactly as uploaded, truth (resize never adds a claim, a number or a badge), Lyra's technical limits (the ratios the model lists), and the user's explicit choices.
---
## How to think about a resize
**What changes and what never does:**
| Changes | Never changes |
|---|---|
| the canvas (ratio, size) | the elements: product, person, phone and screen, headline, subline, CTA, logo, offer badge, background |
| where each element sits, its scale relative to the frame | the words: every text identical, letter for letter (line breaks may move, words may not) |
| how much background is visible (extended, never invented as a new place) | the style: palette, light, color grading, shadows, photo treatment, illustration style |
| the reading order **only** when the new shape forces it (side by side → top to bottom) | the type: font weight, color, style, case |
| the line breaks of a text block | the visual hierarchy: the primary element stays the most prominent |
| | the identity of people, the product, the logo, the UI |
**Four kinds of moves** (decide which one each ratio is, it picks the route):
| Move | Examples | What happens | Risk |
|---|---|---|---|
| **Small step** | 4:5 ↔ 1:1 · 4:5 ↔ 3:4 · 1:1 ↔ 5:4 | the same layout, a little more or less room; gaps tighten or open, the background extends a little | low: a Resize node usually does it |
| **Add height** | 4:5 or 1:1 → 9:16 | the layout stays vertical, the canvas grows up and down; text moves into the new safe zones, the background extends above and below | medium: the 9:16 UI zones push text and CTA inward |
| **Orientation flip** | 9:16 or 4:5 ↔ 16:9 / 1.91:1 · 1:1 → 16:9 | the layout is rebuilt: stacked ↔ side by side, text moves from top / bottom to a side column, the hero moves to a third | high: the model may crop, shrink the text or drop an element |
| **Extreme strip** | → 4:1, 8:1 (banners), 1:4, 1:8 (skyscrapers) | only a row (or a column) of elements fits: hero + headline + CTA side by side | very high: not every element fits; a user decision (below) |
**Extension or recomposition.** Two ways to fill a new frame, often together:
- **Extension (outpainting):** the canvas grows and the new area continues the source background (the same wall, sky, duvet, gradient, texture, light). Best when the source has calm background at the edges.
- **Recomposition:** the elements move and rescale inside the new frame (the headline from the top band to a left column, the CTA under the headline). Needed whenever the new shape doesn't fit the old arrangement.
**Primary element first.** Before planning, name the one element that carries the ad (a face, the phone with the screen, the product, the big headline). In every ratio it stays the most prominent: it gets the space first, then the headline, then the CTA, then the rest.
**Final test for every ratio:** put the new image next to the source at phone size. Same ad at a glance? Every element there, every word identical, the same look? The hero still the first thing you see? Nothing under the platform's UI, nothing jammed against an edge?
---
## Lyra facts: the Image Resize node (Oct 2026)
From `list_node_configs` and the MCP tools; re-check at the start of every build.
- **Action** `image_resize` on the image node type; **preferred model `google/nano-banana-2`**. Nano Banana 2 parameters: resolution 1K / 2K / 4K (default 1K); aspect ratio `match_input_image`, `1:1`, `1:4`, `1:8`, `2:3`, `3:2`, `3:4`, `4:1`, `4:3`, `4:5`, `5:4`, `8:1`, `9:16`, `16:9`, `21:9`.
- **Tool:** `create_image_resize_node` (workflow_uuid, `aspect_ratios`, `model_name`, label). Then `connect_nodes` source → resize node **without a role**. One output per ratio. It generates nothing until `run_node`.
- **Ratios Lyra does not list:** **1.91:1** (Meta link ads, Google App and Display landscape), 2:1, 6:5 (300×250 is 1.2), 9:19.5 (App Store 1290×2796), 6.4:1 (320×50), any exact pixel size. Build the nearest listed ratio with the crop margin planned in (Placements table) and let the user's designer trim it, or ask for the user's own ratio list. Never send an unlisted value to the node.
- **Extreme ratios** (`1:4`, `1:8`, `4:1`, `8:1`) exist only on Nano Banana 2, not on Nano Banana Pro: strips and skyscrapers go through the Resize node (Route A) or the designer (Route D).
- **Whether the resize node shows resolution and an instruction field** is checked after creating it (`get_workflow`). When it shows resolution, set **2K** (4K when the image carries small text or a screen to read). When it has a prompt field that `update_node` can fill, the instruction from the Resize sheet goes there (pattern below). Write in the project notes what the first build shows, so the next build skips the check. No field reachable → Route A runs on the node's own rules, and anything that needs exact placement goes through Route B.
- **The source must have a result.** If the image node made several, the user selects one in Lyra first; the resize uses the selected result. If the source is regenerated later, the resized images are stale: rerun them.
- **The node re-renders the whole image generatively.** It extends and recomposes; it does not crop pixels. So the person, the screen, the logo and every letter are redrawn and must be checked again in every ratio. For pixel-exact assets (a legal-approved pack shot, a logo lockup, a store screenshot), say so and use Route D.
- **What the node does: its system prompt** (Lyra's `Image resize` system prompt), in short:
1. **Preserve all visual elements:** product, headline, CTA, logo, offer badge, background, people; nothing dropped, cropped out or omitted.
2. **Reorganize the layout for the new ratio:** wide → tall stacks the elements vertically, moves text from the sides to the top or bottom and gives the product more vertical space; tall → wide spreads the elements horizontally so text doesn't crowd the product.
3. **Respect platform safe zones:** 9:16 Stories and Reels: top 15% and bottom 20% are UI overlay zones, all critical content (headline, product, CTA) in the center 65% · 4:5 Feed: the full frame is generally safe · 1:1 Feed: center-weighted, balanced on all sides · 1.91:1 link ads: little vertical space, the product and headline first, the CTA visible.
4. **Maintain visual hierarchy:** the most important element (product, face, headline) stays the most prominent; secondary elements don't compete.
5. **Preserve style and colors exactly:** palette, light, grading, shadows, photo treatment; an extended canvas matches the source background seamlessly (texture, color, light); no new colors, gradients or style changes.
6. **Preserve typography:** the text content identical; weight, color and style identical; only the position changes.
7. **Breathing room:** nothing cropped tight against the frame edges; margins around the product, headline and CTA.
8. **Do not improve or enhance:** no upscaling, contrast, sharpening or "fixing"; the goal is the right adaptation, not a better image.
- **Consequences for the skill.** The node already knows the rules; what it doesn't know is **this** ad: which element is primary, where each element should go in each ratio, the exact texts, the screen that must stay identical, and the placement (Stories only, or Reels too). That is what the instruction carries, when the field is reachable. The same 8 rules are written into every Pro recompose prompt (Route B), so every route keeps the same standard.
- **One instruction for several ratios.** The node runs all its ratios from one instruction, so a layout plan per ratio is written as a short list ("9:16: … · 1:1: … · 16:9: …"). If the outputs mix the plans up, split the ratios into one node each.
- **Price** shows on the node next to Run, one generation per ratio; read it and say it before running (base Step 6).
---
## Placements: which ratio, which safe zone
Plan by **placement**, not by ratio: the placement decides the ratio, the pixel size and the safe zone. Specs change: check the platform's current guide before export. Numbers below are directional (Oct 2026).
| Placement | Ratio in Lyra | Export size | Keep key content | Layout note |
|---|---|---|---|---|
| **Meta Feed** (Facebook, Instagram) | **4:5** | 1080×1350 (or 1440×1800) | the full frame is safe; ~5% margins | the master for most statics |
| Meta Feed, square | **1:1** | 1080×1080 | center-weighted, ~5% margins | balanced on all sides |
| **Meta Stories** | **9:16** | 1080×1920 (or 1440×2560) | below the top ~14–15%, above the bottom ~20% | the node's center 65% |
| **Meta Reels** | **9:16** | 1080×1920 (or 1440×2560) | below the top ~14%; headline and hero above the bottom ~20%; **CTA and any small text above the bottom ~30–35%** (the caption overlay grows); ~6% clear on each side | one 9:16 can serve Stories and Reels when it follows the Reels zones |
| Meta link ad, right column, Audience Network | **1.91:1** (not in Lyra) | 1200×628 | build **16:9** and keep the top and bottom ~4% free of key content: the crop from 16:9 to 1.91:1 removes ~7% of the height | the product and headline first, the CTA visible |
| **TikTok** In-Feed | **9:16** | 1080×1920 | below the top ~8–10%, above the bottom ~20–25%, clear of the right ~12% (the action buttons) | check TikTok's safe-zone overlay files |
| **Google App campaigns** (and Demand Gen) | **1:1**, **4:5**, **1.91:1** (via 16:9) | 1200×1200 · 1200×1500 · 1200×628 | Google may crop or assemble the asset: keep text minimal and inside the central area | give all three; a text-free version helps where text gets cropped |
| Pinterest | **2:3** | 1000×1500 | the full frame, ~5% margins | like 4:5 with more height |
| Display banner 300×250 | **5:4** (nearest to 6:5) | 300×250 | ~5% margins | designer trims to the exact pixels |
| Display banner 728×90 | **8:1** | 728×90 | everything readable at 90 px height | Extreme strip rules |
| Mobile banner 320×50 | **8:1** (nearest to 6.4:1) or **4:1** | 320×50 | hero + 2–4 words + CTA only | Extreme strip rules; often a designer job |
| Skyscraper 160×600 | **1:4** | 160×600 | stacked, the CTA at the bottom | Extreme strip rules |
| App Store / Google Play screenshots | exact pixels (1290×2796, 1080×1920) | per store | per store rules | `lyra-ui-motion-video`, Store screenshot sets |
**The default full Meta set** from a 4:5 master: **9:16** (Stories and Reels) + **1:1**; from a 9:16 master: **4:5** + **1:1**. Add **1.91:1** only when link ads, Audience Network or Google run the ad.
**Pixels.** Lyra gives a ratio and a resolution class (1K / 2K / 4K), not exact pixels. 2K comfortably covers 1080-wide exports; the user's designer or the export step scales to the platform's size. Say once that exact pixel sizes are set at export.
---
## The build: four routes
Every image × ratio goes one of four ways. The **route is picked per image and per ratio** in the plan (Best way to build it), and the user sees why.
| Route | What it is | Control over layout | Best for | Weak at |
|---|---|---|---|---|
| **A. Image Resize node** | Lyra's own node (action `image_resize`, **Nano Banana 2**): the source connected, a list of ratios, one output per ratio; it follows the 8 rules above by itself | **medium**: it plans the layout itself; the instruction (when reachable) gives it the plan per ratio | small steps and "add height" moves on simple layouts with calm backgrounds and text far from the edges; many ratios at once; extreme strips (the only route with 4:1, 8:1, 1:4, 1:8); fast and cheap first pass | orientation flips with several text blocks; Pro-level realism (faces, skin, hands); a phone screen that must stay word-for-word exact; precise placement |
| **B. Pro recompose** | a Nano Banana Pro Image Generation node, the approved source connected as [Image1], the **target ratio set in the node**, prompt "Recompose [Image1] for …" with the keep list, the layout plan and every text in quotes; the screenshot and logo uploads connected again when they're on the image | **full**: zone by zone | orientation flips, ads with a person (Pro realism holds), a phone with the real screen, the hero ad of the campaign, anything Route A got wrong | extreme strips (Pro has no 4:1 / 8:1); a layout so different that a rebuild is cleaner |
| **C. Rebuild from the concept card** | a new Pro node at the new ratio from the **original prompt** with only the layout part rewritten for that ratio; the same references connected (persona, screenshot, logo) + the approved image as a style reference with its job stated | full, plus a fresh composition | the source was built in this workflow (its prompt and references exist); a layout that changes completely (a 9:16 stack to 16:9 with three text blocks); carousel sets; when Routes A and B drift twice | costs a full generation; the scene is regenerated, so it is a close sibling of the source, not the same pixels (check against the source) |
| **D. Extension or crop for the designer** | either a **plain crop** outside Lyra (pixel-exact assets), or a Pro **canvas extension** ("Extend the canvas … keep the original image unchanged in the center") with the text then set by the user's designer in Figma | exact | pixel-exact assets (legal-approved, logo lockups); exact pixel sizes Lyra doesn't list (1.91:1 trim, 300×250, 320×50, store screenshots); text the model keeps changing; extreme strips that can't hold every element | needs a designer or a crop tool; outside Lyra |
**How to choose (defaults):**
- **Small step or add height, simple layout, no person in close-up, no readable screen** → A (with the instruction when reachable). Misses fixed with B for that ratio.
- **Orientation flip** (tall ↔ wide) **with two or more text blocks** → B. With one text block and a calm background → A first, B if it crowds the product or drops an element.
- **A realistic person, a face or hands large in the frame** → B (Nano Banana 2 redraws faces with less realism than Pro; the base skill judges realism only on Pro).
- **A phone with the app's screen, or any UI** → B with the screenshot connected again as [Image2] "exactly as supplied" + its key texts, 4K when the screen must be read. Route A only when the screen is small and non-essential, and then checked word by word.
- **The logo on the image** → in B and C the logo upload is connected again as its own reference ("place the logo from [ImageN] exactly as supplied"); in A, check it; if it warps, B or a clean corner for the designer.
- **The source was made in this workflow and the new layout is a different arrangement** → C.
- **Extreme strip** (4:1, 8:1, 1:4, 1:8) → A, after the user has decided what goes into it (Extreme strips below); still crowded → D.
- **Pixel-exact asset, or a size Lyra doesn't list** → D (plain crop, or the nearest listed ratio + designer trim).
- **Two failed tries on one ratio** → change the route (A → B → C → D), never rerun unchanged.
---
## Layout patterns by move
The node's rule 2, made concrete. The Resize sheet writes one of these per ratio, with the shares of the frame.
**Small step (4:5 → 1:1, height −20%).** Keep the zone order; tighten the gaps; the hero shrinks a little or the background extends a little at the sides; the headline keeps its size feel (line breaks may change). 1:1 is center-weighted: the hero centered or on a gentle third, margins even on all sides.
**Add height (4:5 or 1:1 → 9:16).** Extend the background above and below (the same wall, sky, room, gradient). The headline moves into the top clean zone **just below** the top 14–15%; the hero sits in the middle; the CTA above the bottom 20% (above ~30–35% for Reels); the logo inside the safe zone, never in a UI band. The extra height goes to the hero and the background, not to bigger text.
**Remove height (9:16 → 4:5 or 1:1).** The elements come closer together; the extended areas of a 9:16 (sky, floor) are the first to go; nothing primary is cut. The CTA and the logo, often low in a 9:16, move up into the frame.
**Tall → wide (9:16 / 4:5 → 16:9 or 1.91:1).** Rebuild as two columns: the hero on one third (usually the right for left-to-right languages), the text column on the other side (headline on top, subline under it, CTA under the headline, logo small at the bottom of the column). Extend the background sideways. Keep the top and bottom ~4% free when the 16:9 will be trimmed to 1.91:1. The hero never shrinks to a thumbnail to make room: if it doesn't fit, the text gets fewer lines, not a smaller hero.
**Wide → tall (16:9 / 1.91:1 → 4:5 or 9:16).** Stack: headline on top, hero in the middle with more vertical space, CTA below; text that sat beside the product moves above or below it. Extend the background above and below.
**Extreme strips (4:1, 8:1 banners; 1:4, 1:8 skyscrapers).** One row (or one column): the hero (often cropped to its key part: a face, the phone, the product), the headline, the CTA, the logo. Rule 1 says nothing is dropped, but a 728×90 can't always carry a person, a phone, a three-line headline, a subline, a badge and a CTA. If the inventory doesn't fit at a readable size, **ask the user** which element may go (a user decision, never Claude's), or send the strip to the designer (Route D). Never shrink text below what reads at the banner's real size.
**People in any ratio.** Never cut through a face, hands, the phone or the product; head room above the person; a person moves as a whole (no stretching of the body to fill height). Adding height shows more of the body or the room, never a zoomed face.
**A phone with the screen.** The screen stays front-facing and large enough to read in every ratio (half the frame height or more when the screen is the proof); in a wide ratio the phone moves to a third, it doesn't shrink.
**RTL images** (Arabic, Hebrew, Farsi, Urdu, made by `lyra-image-translation`): the text column goes to the right in wide ratios, the hero to the left; never mirror the photo.
**Carousels.** Every card of a set in the same ratio, resized with the same plan (the same grid, the same zone shares), so the cards still line up; continuity elements (a band, a line crossing the card edge) checked across the edges; counter and arrow inside the new safe zones on every card.
---
## Step 1 additions: the source, the placements, the inventory
1. **The source images.** `get_workflow` on the user's workflow (or `list_uploads` for an uploaded file): which image nodes, which selected result, the concept card and the original prompt (they hold the exact texts, the layout map and the references used: persona, screenshot, logo uploads). An image from outside Lyra → `create_upload` + `attach_upload`; if the user attaches it in the chat, Claude also looks at it to make the inventory.
2. **The element inventory.** For each image, every element in reading order: what it is (hero person, phone and screen, product, headline, subline, CTA, logo, offer badge, counter, background), its zone and share of the frame (measured in pixels when Claude has the file: top and bottom of each block divided by the height, left and right by the width), its exact text, and its **priority** (1 = the primary element). Write it into the Resize sheet. Text Claude can't read → ask; never guess.
3. **The placements, not only the ratios.** Ask where the ad runs (Meta Feed, Stories, Reels, TikTok, Google App, link ads, banners) and derive the ratios and safe zones from the Placements table. If the user gives ratios, use them and say which safe zone each will follow (one 9:16 for Stories only, or for Reels too?).
4. **The Brand Kit** (base Reference L) only for checks: the logo file, the colors, forbidden claims. A resize adds no text and no claim, so nothing new is written from the kit; the kit is how Claude spots an element that came out wrong.
5. **Ask only what's needed**, in one message: the placements (or ratios), which images, whether 1.91:1 or banners are needed (they need a designer trim), the screenshot and logo files if the image shows them and they aren't in the workflow, and the user's designer (for Route D).
**Defaults (state, don't ask):** the full Meta set (the master + 9:16 + 1:1) · every element kept, texts identical · a 9:16 that follows the Reels zones, so it serves Stories and Reels · route per image and ratio by the rules above · Nano Banana 2 at 2K for Route A (if the node shows resolution) · Nano Banana Pro at 2K for B and C (4K for small text, a readable screen or a close face) · count 1 per ratio · one Section "Sizes" in the same workflow, to the right of the approved images · languages before sizes · the approved source never edited or overwritten.
**Recommended first run:** A. Pilot ratio (below).
## Step 2 addition: the Resize sheet
The concept the user approves. A user text node "Resize sheet" (a note for the user; it feeds nothing), and the same in the chat:
**1. Per image and ratio: placement, move, route and why**, one line each: "C1 hero static · 9:16 (Stories + Reels) · add height · B (person + phone screen)", "C1 · 1:1 · small step · A", "C1 · 16:9 for 1.91:1 · flip · B, top and bottom 4% clear for the trim".
**2. The element inventory**, one row per element:
| Image · element | Priority | Source zone (share) | Exact text | Notes |
|---|---|---|---|---|
| C1 · Mia + phone with the timer screen | 1 | middle, 22 → 82% of height | screen: "Tonight's plan", "5 min", "Start" | screen identical to screenshot 2 |
| C1 · headline | 2 | top, 0 → 22% | "2 am. Brain won't stop." | heavy white sans, left-aligned, 2 lines |
| C1 · CTA button | 3 | bottom, 85 → 95% | "Try it tonight" | violet #8B7CF6, white text |
| C1 · logo | 4 | bottom-right corner | — | logo.png, small |
| C1 · background | — | full frame | — | dark bedroom, lamp from the right, grey duvet |
**3. The layout plan per ratio**, zones top to bottom (or left to right) with shares, where each element goes, what is extended, the safe zone it follows:
> C1 · 9:16 (Stories + Reels): extend the bedroom above (dark wall) and below (duvet) · 0 → 14%: dark wall, nothing · 15 → 28%: headline, same size feel, left-aligned · 28 → 64%: Mia and the phone, screen front-facing · 64 → 70%: CTA button, centered · 70 → 72%: logo small, centered · 72 → 100%: duvet and phone glow, no key content
> C1 · 1:1: tighten · 5 → 20%: headline · 20 → 80%: Mia and the phone, the room extended a little at the sides · 82 → 93%: CTA centered · logo bottom-right inside the 5% margin
> C1 · 16:9 (trimmed to 1.91:1): two columns, top and bottom 4% clear · left 8 → 45% of the width: headline (top), CTA under it, logo small at the bottom of the column · right 45 → 95%: Mia and the phone on the right third · the dark wall extended to the left
**4. The fit check:** every text keeps its size feel; a line break may move (written in the sheet: "2 am. / Brain won't stop." → one line in 16:9); words never change. A block that can't fit at a readable size in a ratio → re-plan the zone, or ask the user (Extreme strips), never shrink it below readable. Changing the words is not a resize: it's a variant or a translation, and needs the user's yes.
**5. The plan table** (base Step 2) and the credits, in the one approval question (base Step 6).
---
## Best way to build it
The user's explicit choices override any row. Models and prices: base Reference A.
| If the image is | Graph | Models |
|---|---|---|
| **A static with a simple layout, small steps (default)** | approved source (selected result) → **Image Resize node** with the ratios of that route (listed values), the instruction filled from the Resize sheet when the field is reachable → one output per ratio → check → misses fixed with a Pro recompose node for that ratio | nano-banana-2 · nano-banana-pro |
| **A person, a face or hands large in the frame; the hero ad; an orientation flip with several text blocks** | approved source → **one Pro recompose node per ratio** (the ratio set in the node, 2K), the source connected as [Image1] | nano-banana-pro |
| **An image with app UI** (phone shot, UI card, in-app proof) | approved source as [Image1] + the screenshot upload as [Image2] (+ the logo as [Image3]) → one Pro recompose node per ratio, 4K when the screen must be read → word-by-word screen check | nano-banana-pro |
| **The source was built in this workflow and the layout changes completely** | **one Pro rebuild node per ratio**: the original prompt with only the layout part rewritten for the ratio, the same references connected, the approved image as a style reference ("[ImageN] is a style reference only: copy its palette, light, type style and grading; not its layout") | nano-banana-pro |
| **A carousel** (N cards) | per card the same route and the same plan; rebuilt sets through the split pipeline of `lyra-carousel` (the script's layout lines rewritten once for the ratio, the anchors unchanged) | nano-banana-2 / nano-banana-pro |
| **1.91:1** (link ads, Google landscape) | Route A or B at **16:9** with the top and bottom ~4% clear → the designer (or the export step) trims to 1200×628 | nano-banana-2 / nano-banana-pro |
| **Banners and strips** (4:1, 8:1, 1:4, 1:8) | the inventory decision with the user → **Image Resize node** at the strip ratio with the strip plan → check at the banner's real size → the designer trims to exact pixels | nano-banana-2 |
| **An end card or text card for a video** | Route B (or A for a plain card) at the video's ratio; the store badge stays a layer in the Video Editor, never generated | nano-banana-pro · video_composer |
| **Store screenshot sets** | `lyra-ui-motion-video` (Store screenshot sets); exact pixels by the designer | nano-banana-pro |
| **Pixel-exact asset** (legal-approved pack shot, logo lockup) | Route D: a plain crop or the designer's canvas; no generation | — |
| **Languages × sizes** | languages first at the master ratio (`lyra-image-translation`), approved, then each language resized here; count languages × ratios and say the total before running | nano-banana-2 · nano-banana-pro |
| **Many images, many ratios, tight budget** | Route A for every image in one node each → only the misses get a Pro node; Pro recompose only for images with a person or UI | nano-banana-2 → nano-banana-pro |
**Plan example** (base Step 2 table, fictional app Calmly, one approved 4:5 static, full Meta set + 1.91:1):
| # | Node label | Node · model · key settings | Inputs (role) | Stage |
|---|---|---|---|---|
| 1 | Resize sheet | user text (note) | — | — |
| 2 | Ad C1: 2 am POV · 4:5 (approved) | image · nano-banana-pro (existing) | — | — |
| 3 | Screenshot: timer | upload image (existing) | — | — |
| 4 | Logo | upload image (existing) | — | — |
| 5 | C1 · 9:16 · Stories + Reels | image · nano-banana-pro · 9:16 · 4K | 2 ([Image1] source), 3 ([Image2] screen), 4 ([Image3] logo) | 1 |
| 6 | Resize C1 · 1:1 | image resize · google/nano-banana-2 · 1:1 | 2 | 2 |
| 7 | C1 · 16:9 for 1.91:1 | image · nano-banana-pro · 16:9 · 2K | 2, 3, 4 | 2 |
Node 5 is the pilot (the person and the readable screen make it the hardest); node 6 is a small step on Route A; node 7 is a flip on Route B, trimmed to 1.91:1 at export.
Stages for resizing: **1** = the pilot ratio · **2** = the other ratios · **3** = designer trims and exports.
**Canvas.** Section "Sizes" to the right of the approved ads: the Resize sheet note first, then one row per source image, its ratios left to right in the order of the sheet. Labels with the ratio and placement: "C1 · 9:16 · Stories + Reels", "Resize C1 · 1:1", "C1 · 16:9 for 1.91:1". The approved images are never edited or overwritten.
## Run options (resize)
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes, per option:
| Option | Runs | Results | Credits | Time |
|---|---|---|---|---|
| **A. Pilot ratio (recommended)** | the hardest ratio of the set (usually the flip or the 9:16 with a person or a screen), every image | one ratio: shows whether the plan, the route and the safe zones work | {x} | ~1 min |
| B. Whole set | every ratio of every image (Resize nodes + Pro nodes) | the full size set | {x} | ~1 to 3 min |
| C. Everything | languages × ratios | the full multi-language size set | {x} total | ~3 to 5 min |
- Recommend A when there are more than two ratios, any orientation flip, a person or a screen: a fix found on the pilot goes into the plans of the other ratios before credits are spent on them.
- C has no pause to check: a dropped element or a wrong letter repeats in every format. Only when the user accepts that.
- Route A charges one generation per ratio even when only one ratio failed; the fix goes to Route B for that ratio only.
## Prompt rules (resize)
| Node | Write | Avoid |
|---|---|---|
| Resize sheet (text) | per image and ratio: placement, move, route and why; the element inventory with priorities and exact texts; the layout plan per ratio with shares and safe zones; the fit check | prompts meant for the model; changed words |
| Image Resize node | ratios from the model's list only; the source connected without a role; a label with the image and the ratios; the instruction (when the field is reachable): the primary element, the layout plan per ratio, the exact texts, the screen and logo to keep unchanged, the placement's safe zone, "nothing dropped, nothing added" | unlisted ratios (`1.91:1`, `2:1`); several sources into one node; a long brief (the node already has the 8 rules) |
| **Pro recompose** | "Recompose [Image1] for {ratio in words}." → each input's job → the **keep list** (every element by name, every text in quotes, the person, the screen, the logo, palette, light, grading, type style) → the **layout plan** zone by zone with shares → what is extended and how (the same background, seamless) → the safe zone → "The only text in the image is …" → "Do not add, remove, restyle or improve anything." → a short "Avoid …" line | re-describing the scene as a new one; "make it better"; new text; two changes at once (a ratio and a new headline) |
| Rebuild (Pro) | the original prompt word for word with only the layout part rewritten for the new ratio; the same references with their jobs; the approved image as a style reference with its job stated | a new scene, new texts or a new style by accident; the approved image as a layout reference (it pulls the old layout back) |
| Canvas extension (Pro) | "Extend the canvas of [Image1] to {ratio}: keep the original image unchanged in the center, continue the background … seamlessly; add nothing" | moving or redrawing the original part |
**Pattern: instruction for the Image Resize node (Route A, ratios 9:16 and 1:1).**
> Primary element: the woman and the phone. Keep every element and every text exactly. 9:16 (Stories and Reels): extend the dark wall above and the duvet below; headline "2 am. Brain won't stop." just below the top 15%, left-aligned, same size; the woman and the phone in the middle; the button "Try it tonight" and the logo above the bottom 30%; nothing in the top 14% or the bottom 30% but background. 1:1: tighten the gaps; headline at the top, the woman and the phone centered, the button and the logo at the bottom with even margins. Keep the phone screen unchanged. No new text.
**Pattern: Pro recompose, 4:5 → 9:16 (Nano Banana Pro, ratio 9:16 set in the node).**
> Recompose [Image1] for a vertical 9:16 Stories and Reels ad. [Image1] is the approved app ad. [Image2] is the app screen: the phone shows it exactly as supplied, every word and number unchanged: "Tonight's plan", "5 min", "Start". [Image3] is the logo: place it exactly as supplied. Keep exactly: Mia, her face, curly hair, grey hoodie and pose, the phone in her hand, the dark bedroom, the warm lamp light from the right, the colors, the grading, the headline "2 am. Brain won't stop." in the same heavy white sans-serif, left-aligned, and the violet #8B7CF6 button "Try it tonight" with white text. Layout from top to bottom: 0 to 14%: the dark wall, extended, nothing else · 15 to 28%: the headline, the same size as in [Image1] · 28 to 64%: Mia and the phone, the screen front-facing and large · 64 to 70%: the button, centered · 70 to 72%: the logo, small, centered · 72 to 100%: the grey duvet and the phone glow, extended, no text. The extended areas continue the same room, texture and light seamlessly. The only text in the image is the headline, the button and the phone screen. Do not add, remove, restyle or improve anything. Avoid: cropped hands or head, a second person, duplicated objects, new text, a changed screen, sharpened or retouched skin.
**Pattern: Pro recompose, 4:5 → 16:9 for a 1.91:1 link ad (Nano Banana Pro, ratio 16:9 set in the node).**
> Recompose [Image1] for a horizontal 16:9 ad that will be trimmed to 1.91:1: keep the top 4% and the bottom 4% free of anything important. [Image1] is the approved app ad. [Image2] is the app screen: show it exactly as supplied. [Image3] is the logo: exactly as supplied. Keep exactly: Mia, her face, hair, hoodie and pose, the phone and its screen, the bedroom, the lamp light from the right, the colors and the grading, every text and its type style. Layout, two columns: left column, 8 to 45% of the width: the headline "2 am. Brain won't stop." on two lines, left-aligned, the same heavy white sans-serif, then the violet #8B7CF6 button "Try it tonight" under it, then the logo, small, at the bottom of the column, all on the dark wall extended to the left · right, 45 to 95% of the width: Mia and the phone on the right third, the screen front-facing. The extended wall continues the same texture, color and light seamlessly. The only text in the image is the headline, the button and the phone screen. Do not add, remove, restyle or improve anything. Avoid: text over Mia or the phone, a shrunken Mia, new objects, new text, a changed screen.
**Pattern: canvas extension for the designer (Route D, Nano Banana Pro).**
> Extend the canvas of [Image1] to a vertical 9:16 frame. Keep the original image exactly as it is, unchanged, in the center. Continue the dark bedroom wall above and the grey duvet below seamlessly: the same texture, color, grain and the warm lamp light from the right. Add nothing: no objects, no text, no people.
**The 6 rules that matter most here:** (1) plan first: the Resize sheet (inventory, priorities, layout per ratio) approved before any run; (2) recompose, don't crop: every element kept, the primary element first; (3) words, style and colors identical, only positions change; (4) the placement's safe zones, Reels stricter than Stories; (5) the route per image and ratio: A for simple and fast, B for people, screens and flips, C for a new arrangement, D for pixel-exact and unlisted sizes; (6) every ratio checked element by element, letter by letter, before upload.
---
## Truth and brand safety
- The base skill's Truth and disclosure applies to every ratio. A resize **adds nothing**: no claim, number, badge, rating, offer or line that the source didn't carry, and never a "filler" text in the new space.
- The logo, the app icon, store badges and the UI come only from the user's files, exactly as supplied; a badge is best added as a layer by the designer in a new ratio.
- **No improvement** means no retouch either: a person's skin, body or face is not smoothed, slimmed or "beautified" in any ratio.
- The Brand Kit's **forbidden claims are enforced absolutely**: if a model invented text in the extended area, it is removed, whatever it says.
- Remind the user once, in the final report, about the platform's AI label for photoreal synthetic people (every size carries it).
## Deliverable and naming
1. A "Resize sheet" note: routes per ratio, the inventory with priorities, the layout plans, the fit check.
2. One image per source × ratio (× language), in Section "Sizes"; the source untouched.
3. For the media buyer: which images form one ad with an asset per placement, which ratio goes to which placement, which ones the designer trims (1.91:1, banners).
Names: the source's code with the ratio replaced: `B4-A:2amBrain-F:Static-PainPOV-C1-9x16`, `…-C1-1x1`; a 16:9 built for a link ad, after the trim: `…-C1-1.91x1`; banners by pixels: `…-C1-728x90`; languages before the ratio: `…-C1-9x16-de` (as in `lyra-image-translation`). Node labels: "C1 · 9:16 · Stories + Reels".
## Meta and Google setup notes (for the media buyer)
- **Meta placement asset customization:** one ad with an image per placement group: 4:5 (or 1:1) for Feed, 9:16 for Stories and Reels, 1.91:1 for link placements. All versions share the message; only the frame changes. Check the current Ads Manager setup (it changes).
- **Meta's automatic creative enhancements** (cropping, image expansion and similar Advantage+ creative options) can re-crop or extend the images again: when the user delivers recomposed sizes per placement, check those options and turn off the ones that would change them.
- **Google App campaigns** assemble and may crop assets: give 1:1, 4:5 and 1.91:1, keep text short and central.
- TikTok: 9:16 only for In-Feed; check the safe zone against TikTok's overlay file.
---
## Common mistakes (resize)
| Mistake | Prevention |
|---|---|
| A crop or a centered copy instead of a recomposition | Layout plan per ratio; Route A or B, never a plain crop unless pixel-exact |
| Resize run before the layout per ratio was agreed | Resize sheet first; pilot ratio |
| An element dropped (logo, badge, CTA) in the new ratio | Inventory checklist in every check; nothing dropped without the user's yes |
| Text rewritten, shortened or restyled to fit | Words identical; only line breaks may move; re-plan the zone |
| Text shrunk until it's unreadable | Keep the size feel; fewer lines or a re-planned zone, never tiny text |
| Headline or CTA under the Stories / Reels / TikTok UI | Placement safe zones; Reels: CTA above the bottom ~30–35% |
| The hero shrunk to make room for text | Primary element gets the space first |
| A face, hands or the phone cut at the edge | People rules: never cut through them; breathing room |
| The extended area shows a new place, a second person, duplicated objects, a seam | "Continue the same background seamlessly"; check the edges; Route B |
| Colors, light or grading shifted; skin retouched; the image "improved" | Rule 8 in every prompt; check side by side with the source |
| The phone screen redrawn in the resize | Route B with the screenshot connected again, key texts in quotes, word-by-word check |
| The logo warped or redrawn | Logo upload connected again (B, C); a clean corner for the designer if it fails |
| `1.91:1` sent to the node | Only listed ratios; 16:9 with the trim margin, trimmed at export |
| A banner with everything shrunk to fit | Strip plan with the user's decision on what goes in; designer for the exact pixels |
| Nano Banana 2 resize judged as the final realism of a person | People and screens through Pro (Route B) |
| Sizes made before the language was checked | Languages first, approved, then sizes |
| Sizes left stale after the source was regenerated | Rerun them; say it in the report |
| One failed ratio fixed by rerunning the whole resize node | Route B for that ratio only |
| The approved image overwritten | Every ratio is a new node; the source untouched |
| Carousel cards resized with different plans | One plan for the whole set; check the cards side by side |
## Quality gates (resize)
Claude can't open Lyra result links, so after each stage it sends the checklist and asks the user what works and what doesn't. If the user downloads the results and sends them in the chat, Claude can also look at each one, compare it with the source element by element, and draw the placement's safe zones over it with a short script (PIL: semi-transparent bands at the zone percentages) to show what falls under the platform UI.
- **Stage 0 (Resize sheet, Claude checks before sending):** every element of every image in the inventory, with its priority and exact text? Placement and safe zone per ratio? Move and route per ratio, with the reason? Only listed ratios for Lyra, unlisted sizes with a trim plan? The primary element given the space first in every plan? No text changed? Extreme strips decided with the user? Screens and logo connected again in B and C?
- **Stage 1 (pilot ratio):** every element of the inventory present, nothing dropped, nothing added? Every word identical to the source, nothing new in the extended area? The same palette, light, grading, type style? The extension seamless (no seams, repeated patterns, duplicated objects, a second person)? The primary element still the most prominent? Headline, hero and CTA inside the placement's safe zone? Breathing room at every edge, nothing cut? Person natural, not retouched? Screen identical to the screenshot word by word? Logo exact?
- **Stage 2 (all ratios):** the same checks per ratio; the set side by side at thumbnail size reads as one ad; carousel cards line up?
- **Stage 3 (trims and delivery):** 1.91:1 and banners trimmed to exact pixels without cutting key content; export sizes per placement; names with ratios; the placement map handed to the media buyer; AI label reminder given?
Pass = every point that applies holds for every ratio. Fix only the failing ratio, with its credits.
## After the test
Read each placement by its own numbers (cost per result for the goal: install, trial, payer; enough results before calling it). A size that underperforms is a hypothesis: the frame (the hero too small in 9:16, the CTA too low), or the format itself (a recomposed 4:5 is not a native Stories ad; a winning static may need a 9:16-first concept, a UGC video or a carousel there). Save the Resize sheet's plans to the project: the next ad with the same layout resizes from the approved plans.
lyra-image-translation41 KB
View saved version →
---
name: lyra-image-translation
description: "Translate and localize the text on finished app ad images in Lyra (statics, carousel cards, end cards, store screenshot captions) into other languages, keeping the design. Writes the copy for each market first (transcreation, glossary, length check), then picks the build per image - Lyra's Image Translation node, a Nano Banana Pro text-replace edit, a rebuild with localized screenshots, or a clean plate for the designer - and checks every letter. Use for \"translate this ad into German and Japanese\", \"localize the banner for Brazil\", \"the same static in 5 languages\", \"RU / ES / PT versions\", \"translate the carousel\", \"Arabic version\", \"translate the text on the creative\", or a winning static to roll out to new markets. Core image rules come from lyra-static-image-generation."
---
# lyra-image-translation
Image helper skill. Takes an image that is already approved (a static ad, carousel cards, an end card, a store screenshot set) and makes it speak another language: the same ad, the same design, the same promise, with every word written for the new market and checked letter by letter. One output per language, labelled and named so the media buyer can upload them as one multi-language ad.
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**Translation is copywriting first, rendering second.** The hard part is not getting letters onto the image, it's having the right words: a headline that sounds native, fits the zone, keeps the hook and says nothing the Brand Kit doesn't allow. So the words are written and approved **before** any credits are spent, in a Localization sheet, and only then rendered. A node that translates on its own is a tool, never the author.
**Base skill first.** Everything not written here follows `lyra-static-image-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, on-image text rules, realism, models (Reference A), layout library (B), edits (F), UI and logo (G), sizes and languages (H), errors (I), de-slop (J), Meta statics (K), Brand Kit (L). This file adds what is specific to languages and markets. If the two disagree, the user wins, then this file, then the base skill.
**Other skills for their parts.**
- Other **sizes** of the translated images → `lyra-adapt-image` (Image Resize) or a Pro recompose (base Reference F, H). Order: languages first, sizes second (below).
- An image with **app UI** → UI fidelity from `lyra-ui-motion-video`: the interface is never machine-translated; other markets use the localized app's screenshots.
- A **market version** where the person, the room, the props or the voice should change too (a local face for Brazil, a Japanese apartment) → `lyra-audience-variations` (mode B, market markers). This skill changes only words; the moment the picture must change, it is an audience version.
- **Carousels** → `lyra-carousel` (Story Bible, script, Text Split); this file says how a carousel is localized.
- The **headline as a hook** in the new language → the line checks of `lyra-video-hooks` (one idea, simple, specific, true) apply in every language.
- **Video**: voiceover and captions in other languages are in the video skills (`lyra-video-ad-generation` Reference C: one VO script per language, its own voice, length checked). This skill covers only the images inside a video (an end card, a text card, a keyframe with a sign).
- A competitor's ad in another language as the reference → `lyra-copy-competitor-static` (their words are never translated into ours; ours are written from the Brand Kit).
**This is a way of thinking, not a script.** The rules are defaults and good practice; use judgment and say why in one line when you choose differently. Fixed: truth (no claim, price or offer a market's Brand Kit doesn't approve), the Brand Kit's facts and forbidden claims, UI fidelity (localized screenshots only, never a translated interface), the do-not-translate list, Lyra's technical limits (the language codes the node accepts), and the user's explicit choices.
---
## How to think about image translation
**Four things change, in this order of importance:**
| Layer | What it means | Who decides |
|---|---|---|
| **1. Words** | the headline, subline, CTA, labels, bubbles, counters, written natively for the market (not word for word) | Claude writes, the user (ideally a native speaker) approves |
| **2. Fit** | the new text fits its zone at the same size feel: length, line breaks, script, direction (RTL), font support | Claude plans in the sheet, checks after the run |
| **3. Market facts** | price, currency, offer, store name, date and number format, legal lines, the app's name in that market | the Brand Kit per market, or the user |
| **4. The picture** | the person, the place, gestures, objects that don't fit the market | not this skill: `lyra-audience-variations`, if the user wants it |
**Translate, transcreate or rewrite.** Decide per text block and write it in the sheet:
- **Translate** (meaning kept closely): labels, feature names, counters, plain CTAs, anything that must match the app or store wording.
- **Transcreate** (same job, same feeling, new words): headlines, hooks, puns, rhymes, idioms, questions in the customer's voice. "2 am. Brain won't stop." becomes what a tired student in Lisbon would actually think, not a dictionary sentence.
- **Keep** (never translated): the app name, the brand name, trademarked feature names (unless the Brand Kit has a localized name), the logo, store badges (the official localized badge file instead).
**Final test for every language:** would a native speaker in that market read it as an ad made for them, not a translated one? Does every word fit, read at phone size and say only what the Brand Kit allows there?
---
## The build: four routes
Every image × language goes one of four ways. The **route is picked per image** in the plan (Best way to build it), and the user sees why.
| Route | What it is | Control over words | Best for | Weak at |
|---|---|---|---|---|
| **A. Image Translation node** | Lyra's own node (action `image_translation`, model **Nano Banana 2**): the source image connected, a list of language codes, one output per language; it translates only the ad's communication text (hook, headline, value line, CTA, offer, captions) and keeps logos, brand and product names, environment text and UI text as they are (its system prompt, below) | **medium**: it adapts the meaning by itself; a user instruction can steer it (the approved words, the glossary) when the node's instruction field is reachable | statics with short text, many languages at once, fast and cheap first pass; also images with UI when the app has no localized version (the UI stays as is) | exact hooks and puns without an instruction, pt-BR vs pt-PT, long text, small text, complex scripts, layout that needs to move |
| **B. Text-replace edit (Pro)** | a Nano Banana Pro Image Generation node with the approved source connected, `match_input_image`, prompt: "Change only the text…" with every new line in quotes | **full**: the exact approved words | headlines and hooks, every language not in the node's list, regional variants, any image where Route A got a word wrong, the hero ads | very long text (more than ~3 blocks), images where the layout must change |
| **C. Rebuild** | a new Pro node from the original concept card: the same layout map and prompt, the texts in the new language, **localized screenshots** connected | full, plus layout | images with **app UI**, RTL layouts that should be mirrored, text that no longer fits and needs a new layout, carousel sets in the split pipeline | costs a full generation; the scene can shift (connect the original as a reference with its job stated) |
| **D. Clean plate + designer** | the image with the text zones left empty (a Pro edit: "Remove all text…"), the localized text set by the user's designer in Figma | exact, pixel-perfect type and fonts | legal lines, disclaimers, price tables, long copy, scripts the model keeps breaking (small Thai, Devanagari, Arabic), pixel-exact brand fonts | needs a designer; outside Lyra |
**How to choose (defaults):**
- **1 to 3 short text blocks, language in the node's list** → A with an instruction carrying the approved words and the glossary (when the instruction field is reachable), or A as a fast first pass; fix the misses with B.
- **The headline is a hook, a pun or a customer-voice line; the hero ad of the campaign; the user approved exact words and the node takes no instruction** → B.
- **The image shows the app's screen** (a phone, a UI card, a store screenshot) **and the app is localized in that market** → C with the localized app's screenshots, so the ad shows what the viewer will see after install. **The app is not localized** → A is fine: the node keeps UI text unchanged by default. Never instruct the node to translate the UI (it would rewrite the interface "realistically", which breaks UI fidelity).
- **A language or variant the node doesn't list** (pt-BR vs pt-PT, es-MX vs es-ES, fr-CA, Catalan, Croatian…): regional variants of a listed language (pt-BR, es-MX, fr-CA) → A with the variant named in the instruction, when the field is reachable, otherwise B; languages not in the list at all (Catalan, Croatian, Slovak, Bulgarian, Serbian, Kazakh…) → B (or C).
- **RTL** (`ar`, `he`, `fa`, `ur`) → B for a simple headline over a scene; C when the layout has a reading order (chat bubbles, arrows, a list, a CTA corner) that should mirror.
- **Text that must be pixel-exact or legally reviewed** → D.
- **Two failed tries on one block** → D for that block (base rule: clean zone for the designer).
---
## Lyra facts: the Image Translation node (Oct 2026)
From `list_node_configs` and the MCP tools; re-check at the start of every build.
- **Action** `image_translation` on the image node type; **preferred model `google/nano-banana-2`** (Nano Banana 2 params: resolution 1K / 2K / 4K, default 1K; aspect ratio incl. `match_input_image`). Whether the translation node shows these settings is checked after creating it (`get_workflow`); when it does, set **2K** (4K for small text) and **`match_input_image`**, so the output keeps the source's size.
- **Tool:** `create_image_translation_node` (workflow_uuid, `languages`, `model_name`, label). Then `connect_nodes` source → translation node **without a role**. One output per language. It generates nothing until `run_node`.
- **Language codes** (exact, case-sensitive; only these): `ar` Arabic · `be` Belarusian · `bn` Bengali · `zh-CN` Chinese (Simplified) · `zh-TW` Chinese (Traditional) · `cs` Czech · `da` Danish · `nl` Dutch · `en` English · `tl` Filipino (Tagalog) · `fi` Finnish · `fr` French · `de` German · `el` Greek · `he` Hebrew · `hi` Hindi · `hu` Hungarian · `id` Indonesian · `it` Italian · `ja` Japanese · `ko` Korean · `ms` Malay · `mr` Marathi · `no` Norwegian · `fa` Persian (Farsi) · `pl` Polish · `pt` Portuguese · `pa` Punjabi · `ro` Romanian · `ru` Russian · `es` Spanish · `sw` Swahili · `sv` Swedish · `ta` Tamil · `te` Telugu · `th` Thai · `tr` Turkish · `uk` Ukrainian · `ur` Urdu · `vi` Vietnamese.
- **No regional variants**: one `pt`, one `es`, one `fr`, one `en`. Brazil vs Portugal, Mexico vs Spain, Canada vs France, US vs UK spelling → Route B with the exact words.
- **The source must have a result.** If the image node made several, the user selects one in Lyra first; the translation uses the selected result. If the source is regenerated later, the translations are stale: rerun them.
- **What the node does: its system prompt** (Lyra's `image_translation` system prompt), in short:
- **Translates only communication text:** hooks, headlines, value propositions, CTA, offer text, captions and short messaging overlays.
- **Never translates brand elements:** logos, brand names, product names and identity slogans, unless explicitly instructed.
- **Ignores non-communication text:** environment text (street signs, packaging, decor), decorative text.
- **UI:** keeps app or product UI text unchanged **unless the user instruction explicitly asks** to translate it (then it keeps layout and hierarchy). Our rule: never ask; localized screenshots instead (Route C).
- **Preserves the visual:** no change to layout, composition or design; keeps text length visually balanced (no overflow, no awkward wrapping); adapts phrasing for meaning, native sound and the original tone rather than word for word.
- **Consequences for the skill.** The node is a decent transcreator on its own, and it takes **user instructions** ("unless explicitly instructed"). So the approved words, the glossary, the market variant ("Brazilian Portuguese, informal você") and "translate the slogan too" can be given to it as an instruction. The MCP create tool has no instruction field: after `create_image_translation_node`, `get_workflow` and check whether the node has a prompt field that `update_node` can fill. Write in the project notes what the first build shows, so the next build skips the check. No field reachable → Route A runs on the node's own judgment, and exact words go through Route B.
- **One instruction for several languages.** The node runs all its languages from one instruction, so an instruction with exact words per language is written as a short list ("de: headline '…', button '…' · fr: …"). If the outputs mix the languages up, split the languages into one node each.
- **Price** shows on the node next to Run, one generation per language; read it and say it before running (base Step 6).
---
## Step 1 additions: the source, the markets, the glossary
1. **The source images.** `get_workflow` on the user's workflow (or `list_uploads` for an uploaded file): which image nodes, which selected result, the concept card and the original prompt (they hold the exact English texts and the layout map). An image from outside Lyra → `create_upload` + `attach_upload`; Claude also looks at it in the chat if the user attaches it, to read every text block.
2. **The text inventory.** For each image, every text block in reading order with its zone, job (hook, headline, subline, label, bubble, counter, CTA, legal), word and character count, and whether it is on the image or inside a screen (UI). Write it into the Localization sheet. Text Claude can't read → ask; never guess.
3. **The markets, not only the languages.** Ask for the market behind each language: `pt` for Brazil or Portugal? `es` for Spain, Mexico or the US? `en` for the UK? `zh-TW` for Taiwan or Hong Kong? A market decides spelling, words, currency, price and the store.
4. **The Brand Kit per market** (base Reference L): localized app name and feature names, approved claims and **forbidden claims per market** (health and finance claims differ by country), the offer and price per market, tone of voice in that language, localized store badges, localized screenshots. Several kits (one per market) → ask which; never mix two kits in one image.
5. **The glossary (do-not-translate and fixed terms).** App name, brand name, feature names as they appear in the localized app, the CTA as it appears in that store ("Get" / "Install" are the store's own words per language), terms the brand already uses in that market. If the app is localized, its own UI strings are the glossary: a feature is called on the ad what it is called in the app.
6. **Who checks.** Is there a native speaker on the user's side for each language? If not, say once that Claude's translation is a strong draft, not a sign-off, and offer back-translations for the user to judge meaning.
7. **Ask only what's needed**, in one message: the languages and markets (with Claude's recommendation if the user asks "which markets"), the screenshots of the localized app if any image shows UI, prices and offers per market if the image shows one, the native reviewers, how many images.
**Defaults (state, don't ask):** every text block localized, nothing left in English unless it is on the glossary · the same ratio as the source, sizes after languages · Route A for images with short text (with the approved words as its instruction when possible), Route B for hero ads and hooks when the node takes no instruction, Route C for images with UI when the app is localized in that market · Nano Banana 2 at 2K for Route A (if the node shows resolution), Nano Banana Pro at 2K for B and C (4K for small text) · count 1 per language · one Section "Languages" in the same workflow (a Lyra variation per market only when the picture changes too) · the ad copy outside the image (primary text, headline field) localized in the same sheet.
**Recommended first run:** A. Pilot language (below).
## Step 2 addition: the Localization sheet
The concept the user approves. A user text node "Localization sheet" (a note for the user; it feeds nothing), and the same table in the chat:
**1. Per image: route and why**, one line each: "C1 hero static · B for de, fr, pt-BR (hook line transcreated); A for it, nl, pl (short headline, fast)", "C2 phone shot · C (UI: localized screenshots)".
**2. The copy table**, one row per text block × language:
| Image · block | Job | Source (EN) | Chars | Target (de) | Chars · ratio | Back-translation | Mode | Notes |
|---|---|---|---|---|---|---|---|---|
| C1 · headline | hook | "2 am. Brain won't stop." | 23 | "2 Uhr nachts. Kopf ist an." | 26 · 113% | "2 at night. Head is on." | transcreate | fits the top 22% on 2 lines |
| C1 · CTA | CTA | "Try it tonight" | 14 | "Heute Nacht testen" | 18 · 129% | "Test tonight" | translate | button widens ~15%; OK |
**3. The glossary** (do not translate / fixed terms) and the **market facts** (price, currency, offer, store wording) per language.
**4. The fit check**: every block with a length ratio over about **120%** is shortened (transcreated tighter), never shrunk to fit; over **140%** → the zone is rethought (two lines, Route C) and said in the plan.
**5. The ad copy outside the image**, per language: primary text (~125 characters before "more" on Instagram), headline field (~27 to 40 characters), CTA button (Meta's own localized buttons).
**6. The plan table** (base Step 2) and the credits, in the one approval question (base Step 6).
### Writing the copy
- **Write in the language, don't translate the English.** Start from the block's job and the audience's words in that market (store reviews in that language are the best source: customer words). Then check the meaning against the source.
- **The hook stays a hook.** The same feeling, the same mechanism (a question stays a question, a confession stays first person), the same short length. The line checks of `lyra-video-hooks`: one idea, simple, specific, true, natural said aloud.
- **Formal or informal "you".** Decide per market and keep it across every image, card and the ad copy: German du / Sie, French tu / vous, Spanish tú / usted, Portuguese você / tu, Russian ты / вы, Japanese register, Korean speech level. Default: the informal form for consumer apps unless the Brand Kit's tone says otherwise; write the choice in the sheet.
- **Same claims, same strength.** A translation never makes a claim stronger ("helps you sleep" never becomes "cures insomnia"); health, money and result words are checked against that market's approved claims.
- **Numbers, dates, prices, units in the local format:** decimal comma (1,99 €) or point ($1.99), currency symbol position, 24-hour time ("2 Uhr", "2h"), date order, metric units. Prices and offers come from the Brand Kit per market, never converted by Claude.
- **Local punctuation and typography:** French spaces before ! ? : ; and « guillemets » · German „quotes“ · Russian «ёлочки» · Spanish ¿ ¡ · Japanese and Chinese full-width punctuation 。、「」 · no italics or uppercase for CJK · Turkish dotted İ / dotless ı in capitals ("İNDİR", not "INDIR") · German nouns capitalised, ß kept in lower case (or SS in caps) · Greek drops accents in all caps.
- **Line breaks are part of the copy.** Write where the line breaks in the sheet ("2 Uhr nachts. / Kopf ist an."); never break a word, a number from its unit, or a particle from its word (French "!" never alone on a line; Japanese breaks at phrase boundaries).
- **Length guide** (against English, directional): German, Dutch, Finnish, Russian, Ukrainian, Polish, Greek often **+20 to 35%** (German and Finnish long compounds can break a narrow zone) · French, Spanish, Italian, Portuguese, Romanian **+15 to 30%** · Japanese, Chinese, Korean **fewer characters** but each glyph needs more height: keep the same size feel, don't shrink · Arabic, Hebrew, Farsi, Urdu about the same length, **right to left** · Thai no spaces between words (line breaks need a native speaker) · Hindi, Bengali, Marathi, Punjabi, Tamil, Telugu: complex scripts with stacked forms, the riskiest for image models. Short lines grow the most: a 2-word CTA can double.
---
## Fit, scripts and direction
**Fonts per script.** The source's type style may not exist in the target script (many display fonts have no Cyrillic, Greek, Vietnamese, Arabic or CJK). In Routes B and C describe the style **for that script**: "a heavy rounded sans-serif, Cyrillic", "a bold Japanese gothic (sans-serif) typeface", "a bold modern Arabic sans-serif, right-aligned". If the Brand Kit has a font per script, name it (the model may not match it exactly: say so once). Check the result for mixed fonts (one word in another style) and missing diacritics (ä ö ü ß, é è à ç, ą ę ł ś ż, ă ș ț, đ ơ ư and Vietnamese tone marks, ё й).
**RTL (Arabic, Hebrew, Farsi, Urdu).**
- The text reads right to left and is right-aligned; numbers and Latin brand names stay left to right inside the line.
- The **reading order of the layout** flips when it carries meaning: chat bubbles (the user's bubble moves to the left, the app's to the right), arrows and "→ swipe" cues, progress counters, a CTA corner, before / after (before on the right). A photo with a headline usually doesn't need mirroring; a layout with an order does (Route C, the layout map mirrored in words). Never mirror a photo with text, a logo, a phone or a face (it looks wrong).
- Check every RTL output with a native reader: models often reverse letter order, break the joins between Arabic letters, or put the punctuation on the wrong side.
**CJK (Japanese, Chinese, Korean).** Fewer characters, so lines get short and the zone can look empty: keep the size feel and the zone, not the line count. Vertical text only if the source is vertical. Simplified vs Traditional Chinese are different scripts and audiences (`zh-CN` mainland and Singapore, `zh-TW` Taiwan; Hong Kong uses Traditional with Cantonese wording). Japanese mixes kanji, kana and Latin: the app name often stays in Latin or uses the app's own katakana name.
**Complex Indic scripts and Thai.** Highest risk of broken letters in generation. Keep the text short, large, on a clean zone; check with a native reader; after one failed fix go to Route D for that block.
**Text over the picture.** A longer line can grow over a face, the phone or the product. The safe zones and clean zones of the base skill (layout map) still hold in every language; if the text no longer fits its clean zone, it's Route C (the zone re-planned), not a smaller font.
---
## Best way to build it
The user's explicit choices override any row. Models and prices: base Reference A.
| If the image is | Graph | Models |
|---|---|---|
| **A static with short text (default)** | approved source (selected result) → **Image Translation node** with the languages of that route (codes from the list), the instruction filled from the Localization sheet when the field is reachable → one output per language → check → misses fixed with a Pro text-replace node per language | nano-banana-2 · nano-banana-pro |
| **A hero ad, a hook or pun headline, exact approved words, or a regional variant** | approved source → **one Pro text-replace node per language** (`match_input_image`, 2K), the source connected as [Image1] | nano-banana-pro |
| **An image with app UI** (phone shot, UI card, in-app proof) | localized screenshots uploaded (one per screen per language) → **one Pro rebuild node per language**: the original prompt with the texts in that language and the localized screenshot connected; the original approved image connected as a scene reference with its job stated ("keep the person, light, framing and layout; not its text or screen") → word-by-word screen check | nano-banana-pro |
| No localized app (the UI exists only in English) | the screen stays in English (it is what the user will see after install), or the screen faces away / is replaced by a non-UI visual; say it in the plan; never translate the UI in the image | nano-banana-pro |
| **RTL with a reading order** (chat, arrows, list, before / after) | Pro rebuild with the layout map mirrored in words, the texts in quotes, right-aligned | nano-banana-pro |
| **Carousel** (N cards) | per card the same route; terms, formality and the counter identical across cards; split pipeline: a localized carousel script per language (the anchors identical, only the quoted texts change) → Text Split → cards, the persona and card 1 of the same language as references | nano-banana-2 / nano-banana-pro |
| **End card or text card for a video** | the end card image through Route B or C; the localized store badge file as a layer in the Video Editor; VO and captions by the video skills | nano-banana-pro · video_composer |
| **Store screenshot set** (App Store / Google Play) | the localized app's screenshots + the caption written in that language, one Pro node per slot (`lyra-ui-motion-video`, Store screenshot sets); never Image Translation | nano-banana-pro |
| **Legal line, disclaimer, price table, long copy** | Pro clean-plate edit ("Remove all text, keep everything else exactly") → the user's designer sets the localized text in Figma | nano-banana-pro |
| **Languages × sizes** | languages first at the master ratio, approved, then each language resized or recomposed (`lyra-adapt-image`, base Reference H); count languages × ratios and say the total before running | nano-banana-2 · nano-banana-pro |
| **The picture should change for the market too** | `lyra-audience-variations` (mode B, a Lyra variation per market); this skill writes its texts | as that skill |
| **Many languages, tight budget** | Route A for all in one node → only the misses get a Pro node; Pro rebuild only for UI images | nano-banana-2 → nano-banana-pro |
**Plan example** (base Step 2 table, fictional app Calmly, one static, 4 markets):
| # | Node label | Node · model · key settings | Inputs (role) | Stage |
|---|---|---|---|---|
| 1 | Localization sheet | user text (note) | — | — |
| 2 | Ad C1: 2 am POV · 4:5 (approved, EN) | image · nano-banana-pro (existing) | — | — |
| 3 | Translate C1 · it, nl, pl | image translation · google/nano-banana-2 · languages it, nl, pl | 2 | 1 |
| 4 | C1 · de · 4:5 | image · nano-banana-pro · match_input_image · 2K | 2 ([Image1] source) | 1 |
| 5 | C1 · pt-BR · 4:5 | image · nano-banana-pro · match_input_image · 2K | 2 | 1 |
| 6 | C1 · ar · 4:5 (rebuild, RTL) | image · nano-banana-pro · 4:5 · 2K | 2 (scene reference) | 2 |
| 7 | C1 · de · 9:16 + 1:1 (after approval) | image resize · google/nano-banana-2 | 4 | 3 |
Stages for translation: **1** = the pilot language and Route A (fast) · **2** = the other languages and the rebuilds · **3** = sizes.
**Canvas.** Section "Languages" to the right of the approved ads: the Localization sheet note first, then one row per source image, its language outputs left to right in the order of the sheet. Labels with the code: "C1 · de · 4:5", "Translate C1 · it, nl, pl", "C2 · ja · 4:5 (rebuild, UI ja)". The approved English images are never edited or overwritten.
## Run options (translation)
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes, per option:
| Option | Runs | Results | Credits | Time |
|---|---|---|---|---|
| **A. Pilot language (recommended)** | the hardest language of the set (the longest, e.g. `de`, or an RTL one), every image | one language, all images: shows whether the route, fit and fonts work | {x} | ~1 min |
| B. Fast pass | Route A for all its languages in one node + the Pro nodes | every language | {x} | ~1 to 2 min |
| C. Everything | all languages → sizes | languages × ratios | {x} total | ~3 to 5 min |
- Recommend A when there are more than two languages or any RTL / CJK / Indic script: a fix found on the pilot is applied to every language before credits go on them.
- C has no pause to check: a wrong word is resized into every format. Only when the user accepts that.
- Route A charges one generation per language even when only one word was wrong; fixes go to Route B for that one language.
## Prompt rules (translation)
| Node | Write | Avoid |
|---|---|---|
| Localization sheet (text) | route per image and why; the copy table (source, job, chars, target, ratio, back-translation, mode, line breaks); glossary; market facts; ad copy outside the image | prompts meant for the model; untraced prices or claims |
| Image Translation node | the language codes from the list only; the source connected without a role; a label with the image and the codes; the instruction (when the field is reachable): the market variant and formality, the exact approved texts per language and block, the glossary, what stays in English | codes not in the list (`pt-BR`, `es-MX`); several sources into one node; "translate the UI"; a long brief (the node only needs the words and the rules) |
| **Text-replace edit (Pro)** | "Change only the text." → "[Image1] is the approved ad: keep the person, face, pose, the phone, the background, the light, the layout, the colors and the button shape exactly." → each block: its zone, the old text and the new text in quotes, the type style for this script, alignment, color, size feel → "The only text in the image is …" → "Avoid: extra text, mixed fonts, missing accents, changed layout." | re-describing the scene; "translate the text" without the words (the model would write its own); two changes at once (text and light) |
| Rebuild (Pro) | the original prompt word for word with only the quoted texts replaced, the type style for the script, the localized screenshot "exactly as supplied" with its key texts in that language, the original image's job stated if connected | a new layout or scene by accident; the English screenshot |
| Clean plate (Pro) | "Remove all text from [Image1]: the headline, the subline and the button label; keep the button shape, every color, the person, the scene and the layout exactly; leave the text areas as clean, empty background." | removing the logo or the button with the text |
**Pattern: instruction for the Image Translation node (Route A, languages de and pt).**
> Use exactly these texts. de (German, informal du): headline "2 Uhr nachts. / Kopf ist an." on two lines; button "Heute Nacht testen". pt (Brazilian Portuguese, informal você): headline "2 da manhã. / A cabeça não para." on two lines; button "Teste hoje à noite". Keep "Calmly" and the logo as they are. Keep the phone screen unchanged. No other text.
**Pattern: text replace, German (Nano Banana Pro, `match_input_image`).**
> Change only the text. [Image1] is the approved app ad: keep Mia, her face, pose and grey hoodie, the dark bedroom, the phone and its screen, the lamp light, the framing, the colors and the violet button shape exactly. Top 22%, on the dark wall: replace the headline "2 am. Brain won't stop." with "2 Uhr nachts. / Kopf ist an." on two lines, in the same heavy white sans-serif, very large, left-aligned. Bottom: replace the button text "Try it tonight" with "Heute Nacht testen", white, centered on the violet #8B7CF6 button; the button may be slightly wider. The only text in the image is the headline, the button and the phone screen, which stays exactly as it is. Avoid: extra text, English words left over, mixed fonts, missing umlauts, changed layout.
**Pattern: text replace, Arabic headline over a photo (Nano Banana Pro).**
> Change only the text. [Image1] is the approved app ad: keep the woman, her face and pose, the bedroom, the light, the framing and the colors exactly; do not mirror the photo. Top 22%: replace the headline "2 am. Brain won't stop." with the Arabic headline "[approved Arabic text from the Localization sheet]", written right to left and right-aligned, in a bold modern Arabic sans-serif, white, very large, the letters correctly joined. Bottom: replace the button text with "[approved Arabic CTA]", centered. The only text in the image is the headline and the button. Avoid: reversed letters, disconnected Arabic letters, Latin text, extra text.
(The bracketed parts are filled from the sheet before the node is built: no placeholders in a final prompt, base rule.)
**The 6 rules that matter most here:** (1) words first: the Localization sheet approved before any run; (2) transcreate the hook, translate the labels, keep the glossary; (3) the route per image: A for simple and fast, B for exact words, C for UI and layouts with an order, D for legal and long copy; (4) never translate an interface: localized screenshots or no screen; (5) fit by rewriting, never by shrinking; (6) every letter checked in every language, by a native reader where possible, before sizes or uploads.
---
## Truth, markets and brand safety
- The base skill's Truth and disclosure applies in every language. A translation adds no claim, number or offer and never strengthens one.
- **Claims and offers per market.** A claim approved in the US may not be allowed in Germany or Brazil (health, finance, "free", "#1"); a price or trial length can differ by market. Only what the market's Brand Kit or the user approves; no price conversion by Claude.
- The Brand Kit's **forbidden claims are enforced absolutely** in every language, including in words that only become a forbidden claim in translation.
- **Brand safety** (Lyra's System Preamble): no profanity, no political or religious statements, no unsubstantiated health claims, no competitor disparagement; slang and idioms checked for second meanings in that market (a native reader catches what Claude may not).
- **Store wording and badges:** the localized official badge files ("Laden im App Store", "Disponible sur Google Play"), never generated, never translated by a model.
- Local ad rules differ (alcohol, gambling, health, finance, children, and in some countries required language versions or disclaimers): name them once when the category is sensitive; not legal advice, the user's team checks.
- Remind the user once, in the final report, about the platform's AI label for photoreal synthetic people (every language version carries it).
## Deliverable and naming
1. A "Localization sheet" note: routes, the copy table with back-translations, glossary, market facts, the ad copy outside the image.
2. One image per source × language (× ratio, when sizes are made), in Section "Languages"; the source untouched.
3. For the media buyer: which images form one multi-language ad, the default language, the primary text and headline per language.
Names: the source's code + `-{lang}` (the market when it matters): `B4-A:2amBrain-F:Static-PainPOV-C1-4x5-de`, `…-C1-4x5-pt-BR`, `…-C1-4x5-ar`; carousels `…-Card3-4x5-ja`; sizes after the language: `…-C1-9x16-de`. Node labels: "C1 · de · 4:5".
## Meta and TikTok setup notes (for the media buyer)
- **Meta multi-language ads** (language customization): one ad with a default language and versions per language (image, primary text, headline, description, CTA); Meta shows each person the version that matches their language. All versions should share the format, the ratio set and the message; only the language changes. Ads Manager can also auto-translate the **text fields**, never the text **on the image**: that is this skill's job. Check the current setup in Meta's guide (it changes).
- Separate ad sets per country are still common when prices, offers or claims differ by market.
- TikTok: one ad per language, targeted by language or country.
- Test the translated winner against a native-made concept in the bigger markets: a translated winner is a hypothesis there, not a proven ad.
---
## Common mistakes (translation)
| Mistake | Prevention |
|---|---|
| Image Translation run before the words were agreed | Localization sheet first; Route A only where wording is flexible |
| The hook translated word for word, flat and long | Transcreate the hook: same job, same feeling, native words, line checks |
| The app name or feature name translated | Glossary: do-not-translate list; check Route A outputs for it |
| The node instructed to translate the UI, or an English screen left in an ad for a market where the app is localized | Never instruct UI translation; localized app → Route C with localized screenshots; not localized → the node keeps the UI unchanged by default |
| A brand slogan expected to be translated, but the node kept it | The node keeps identity slogans by default; say it explicitly in the instruction if the Brand Kit has a localized slogan |
| `pt` used for Brazil and Portugal alike, `es` for Spain and Mexico | Market per language; regional variants by Route B with exact words |
| Code not in the list sent to the node | Codes from `list_node_configs` only; others by Route B |
| Text shrunk to fit | Rewrite tighter; over ~140% re-plan the zone (Route C) |
| A longer headline grows over the face or the phone | Clean zones of the layout map hold in every language |
| Formal and informal "you" mixed across images or cards | One choice per market, written in the sheet |
| Price converted or offer copied from the US kit | Market facts from the Brand Kit per market |
| Missing accents, mixed fonts, wrong quote marks, "INDIR" in Turkish | Typography rules per language; check every letter |
| Arabic letters disconnected or reversed, bubbles not mirrored | RTL rules; native check; Route C when the layout has an order |
| One wrong word fixed by rerunning the whole translation node | Route B for that language only |
| Sizes made before the language was checked | Languages first, approved, then sizes |
| Translations left stale after the source was regenerated | Rerun them; say it in the report |
| The English image overwritten | Every language is a new node; the source untouched |
| Claude's translation presented as final for a language it can't fully judge | Back-translation in the sheet; native reviewer named or offered |
| Store badge redrawn in the new language | Official localized badge files only |
## Quality gates (translation)
Claude can't open Lyra result links, so after each stage it sends the checklist and asks the user (or the native reviewer) what works and what doesn't. If the user downloads the results and sends them in the chat, Claude can also read every text block itself and compare it with the sheet, letter by letter.
- **Stage 0 (Localization sheet, Claude checks before sending):** every text block of every image inventoried? Market per language decided? Route per image with the reason? Hooks transcreated, labels translated, glossary kept? Back-translation for every line? Length ratios checked, nothing over ~120% without a rewrite? Formality, number, date, currency and punctuation per market? Claims, prices and offers traced to the market's Brand Kit, forbidden claims absent? Codes from the node's list for Route A? UI images on Route C with localized screenshots (or the screen plan)?
- **Stage 1 (pilot language):** every word identical to the sheet, nothing English left (except the glossary)? Accents and special letters right? One font style, the same size feel? Text inside its clean zone, nothing over a face, the phone or the product? Layout, colors and scene unchanged? RTL: right to left, letters joined, order mirrored where planned?
- **Stage 2 (all languages):** the same checks per language; brand and app names untouched; the screens identical to the localized screenshots; the carousel's terms and counters identical across cards; a native reader's yes where available?
- **Stage 3 (sizes and delivery):** nothing cropped, texts re-checked in each ratio; names with language codes; the multi-language set listed for the media buyer; the ad copy per language handed over; AI label reminder given?
Pass = every point that applies holds for every language. Fix only the failing language and block, with its credits.
## After the test
Read each language by its own market's numbers (cost per install, trial, payer; enough results per market before calling it), not against the English average: markets have different CPMs and conversion. A language that underperforms is a hypothesis: the words (try a second transcreation of the hook), the market (the picture may need a local version: `lyra-audience-variations`), or the offer. Save the Localization sheet and the glossary to the project: the next ad in that market starts from the approved terms, formality and tone.
lyra-result-check20.9 KB
View saved version →
---
name: lyra-result-check
description: "Check a finished Lyra video or image ad by looking at it, automatically after every final render. Opens the result file in a browser, takes frames at every spoken line and every cut (every card, size and language for images) at full resolution, checks faces, hands and fingers, phone screen text and the logo, captions over faces and warped text, measures the sound (levels, clipping, silence, hard end, music under the voice), then reports \"checked 14 frames, 2 problems\" with the problem frames as pictures and a fix for each through lyra-fix. No browser → a check list with timecodes for the user. Use after a render or a fix, and for \"check the video\", \"look at the result\", \"any defects?\", \"is it ready to launch\", \"check the statics\"."
---
# lyra-result-check
Quality check skill for every Lyra creative, video and image. The creative skills build the ad and `lyra-video-editor` renders it; this skill looks at the finished result the way a reviewer would, frame by frame, measures its sound, and says what is broken before the ad goes to the media buyer. Fixing is not done here: every problem goes to `lyra-fix`.
**The goal.** The user gets one short answer: "Checked 14 frames, 2 problems", each problem with its time, scene, a picture of the frame, what is wrong and how to fix it with its price. Nothing invented, nothing graded without being seen or measured.
**Core rules come from the base skills.** Part 1 of `lyra-video-ad-generation` (video) or `lyra-static-image-generation` (images) holds the shared steps: links, picking a result, open canvas, credits. The edit itself (composition, captions size and place) is described in `lyra-video-editor`. Fixes follow `lyra-fix`.
**When it runs.**
- **Automatically, after every final result.** A video skill or `lyra-video-editor` rendered the final video, or an image skill finished its images → run the check straight away, without asking (it costs no credits), and put its report into the final report.
- **After a fix:** `lyra-fix` reran a part → check only the frames of the fixed part and the cuts around it.
- **On request:** "check the video", "look at the result", "anything broken?", "can we launch it?", a link to an older render.
- Not after intermediate stages (keyframes, single clips before the edit): those are checked in the stage itself.
**This is a way of thinking, not a script.** Fixed: look before judging, frames chosen from the edit (not at random), say what was checked and what wasn't, every problem with a time, a picture and a fix, sound measured but never claimed "heard", fixes only through `lyra-fix` and only after a yes.
---
## What Claude can and can't check
| Can check | How | Can't check (asks the user) |
|---|---|---|
| Faces: identity, eyes, teeth, skin, the same person across cuts | frames | Pronunciation of the app name, voice tone, whether the voice is clear |
| Hands and fingers, objects held | frames at full resolution | Lip sync (needs sound and motion together) |
| Phone screen text, UI, the logo and icon | frames, against the user's screenshot and logo | Motion between frames: morphing, flicker, jitter (frames are still; only big ones are caught) |
| Captions: over a face, size, safe zone, words | frames, against the script | Pacing and how the ad feels |
| Text on images and on screen | frames, letter by letter | |
| Cuts: black frames, a jump of person, outfit or props, the end card | frames on both sides of each cut | |
| Sound: levels, clipping, silence at the start, a hard stop at the end, music under the voice in dB | measured in the browser (Step 4) | |
---
## Step 1. Find the result and read the workflow
1. `get_workflow` now, not from memory.
2. **The final video.** The final file is a link `https://lyra.splitmetrics.com/media/static/…mp4`. Where to get it:
- **rendered in this chat:** the `url` from `get_run_results` of the Video Editor run;
- **rendered earlier:** the tools return a result only for a run made in this chat. Open the workflow in the browser, press play on the node's preview and read the file link from the page (`document.querySelector('video').currentSrc`), or take the latest render from the Video Editor's **Results** drawer, or ask the user for the video link (one line: "Send me the link to the final video, from the Video Editor's Results"). Then move the tab off the workflow before any edit;
- **no Video Editor yet** (the workflow ends on a clip): check the clip itself the same way, say that there is no edit yet (no captions, music or end card), and offer the edit by `lyra-video-editor`;
- **the parts of the edit:** every clip, voiceover, music and image in the Video Editor's `video_rendering_composition` has a direct file link in `assetUrl`, with `startMs`, `trim`, `volume` and its track's `volume` and `muted`. Use them for the sound check (Step 4) and, when the render can't be had, to check the clips themselves (say then that captions, text layers and the end card were not checked).
- Several Video Editors (cutdowns, languages) → check each one asked for, report each.
3. **The images.** The `url` from `get_run_results` when they were made in this chat; otherwise open the workflow in the browser and open each image node's result, or ask for the links. Statics, carousel cards, sizes, languages: every version.
4. **What it should look like,** to check against:
- the script: the scenes, the lines (who says what and when), on-screen text marked for post, the CTA;
- the composition: each clip's `startMs` and `durationMs`, layers (UI inserts, end card, text), the caption track (size, `position`), `canvas.durationMs`;
- the user's app screenshots and logo (the pink section), for the screen and logo check;
- the planned text on images (headline, offer, CTA, card text) and the Brand Kit's app name.
5. No result yet, or the render failed → nothing to check: say so and offer to finish or fix the node first.
## Step 2. Pick the frames (video)
Frames come from the edit, not at random. Build the list from the composition and the script:
| Moment | Frame | Why |
|---|---|---|
| **Start** | 0.0 s (frame 0) | hook text and first caption word visible, no black frame |
| **Every spoken line** | the middle of the line (from the script timing, the VO, or the caption track's words) | face and mouth while speaking, captions over the face, the words |
| **Every cut** | ~0.1 s before and ~0.1 s after the cut (clip boundaries from `startMs`; shot cuts inside a multi-shot clip from the script) | person, outfit, props and place match, no black frame, no half frame |
| **Phone and UI moments** | the middle of each shot where the screen is visible, and of each UI insert | screen text, UI, logo |
| **Hands in action** | the middle of every shot where a hand holds or taps something | fingers, grip |
| **End card** | its first frame and the last frame of the video | complete, logo, offer, CTA, not cut short |
- Merge frames closer than ~0.3 s.
- Usual count: 10–20 frames for 15 s, 15–30 for 30 s, up to ~40 for 60–120 s (short drama: lines and cuts first, hands and screen moments where they are).
- After a `lyra-fix`: only the fixed part, the cut before it and the cut after it.
- Write the list down as a table (time · scene · what to look at) before opening anything: it is also the user's check list if the browser fails.
## Step 3. Take and look at the frames
Needs a browser **signed in to Lyra** (Claude in Chrome or the built-in browser). The result files are protected: they open only with the Lyra sign-in cookie, so they can't be downloaded into a shell, and a browser that isn't signed in gets an XML page with `MissingKey` / "Missing Key-Pair-Id" instead of the video. Then ask the user to sign in to Lyra in that browser (never type their password yourself) and open the file again.
1. **Open the file itself** (the `.mp4` or image link) in a new tab, not the workflow page: an open canvas can write its old state over later tool edits, and on the file's own page the frames can be drawn and measured.
2. **Hide the player controls and seek** to each time on the list:
```js
const v = document.querySelector('video'); v.pause(); v.controls = false;
v.currentTime = 7.4;
await new Promise(r => v.addEventListener('seeked', r, { once: true }));
await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r))); // let the frame paint
```
The controls bar covers the bottom of the frame, exactly where captions and the end card button sit: always hide it. Without the two animation frames after `seeked`, the first drawing can come out empty: if a contact sheet is blank, draw it again.
3. **Look at full resolution.** The video in the window is small (a 1080×1920 video shows at ~420×750 px), too small for fingers and screen letters. Draw the frame, or a part of it, into a canvas over the page at its real pixels and take the screenshot of that:
```js
let c = document.getElementById('qc') || Object.assign(document.body.appendChild(document.createElement('canvas')), { id: 'qc' });
c.style.cssText = 'position:fixed;left:0;top:0;z-index:9;background:#000';
const [sx, sy, sw, sh] = [300, 650, 480, 480]; // the part to look at, in video pixels
c.width = c.height = Math.min(innerWidth, innerHeight);
c.getContext('2d').drawImage(v, sx, sy, sw, sh, 0, 0, c.width, c.height);
```
- **Overview first:** a contact sheet, 6–9 frames of the list drawn small side by side in one canvas, one screenshot. It shows continuity (the same face, outfit, props) at a glance.
- **Then the details:** a crop of every face, hand, phone screen, caption and logo on the list.
- Remove the canvas when done (`document.getElementById('qc')?.remove()`).
4. **Images:** open each image link; the same canvas crops for every text block, face, hand and logo. Carousels: every card. Sizes and languages: every version (a resize can drop or squash text; a translation can break letters).
5. **Keep the problem frames.** For every problem, save the crop that shows it (the screenshot or zoom tool's save-to-disk option) to show the user in the report.
6. Close the tabs you opened. If the workflow was open in a tab before, leave it as it was.
**No browser** → Step 7 (check list for the user).
## Step 4. Measure the sound
Claude can't hear, but it can measure. On the file's own page (the render, or a part's `assetUrl`) decode the audio and read its levels:
```js
const buf = await fetch(location.href).then(r => r.arrayBuffer());
const a = await new OfflineAudioContext(1, 44100, 44100).decodeAudioData(buf);
const d = a.getChannelData(0), win = Math.round(a.sampleRate * 0.5);
let rms = [], peak = 0, clip = 0;
for (let i = 0; i < d.length; i += win) {
let s = 0;
for (let j = i; j < Math.min(i + win, d.length); j++) { s += d[j] * d[j]; const x = Math.abs(d[j]); if (x > peak) peak = x; if (x > 0.99) clip++; }
rms.push(Math.round(20 * Math.log10(Math.sqrt(s / win) + 1e-9)));
}
({ dur: a.duration, peak, clipped: clip, rms_dB_every_0_5s: rms.join(' ') })
```
Read it like this:
- **Silence at the start:** the first 0.5 s far below the rest (more than ~20 dB) → the voice or music starts late; the hook loses its first second.
- **A hard stop:** the last 0.5 s drops straight to silence (to −60 dB and lower) from a normal level, with no fade before it → the music or the voice is cut off.
- **Clipping:** samples at full scale (`clipped` > 0, peak ≈ 1.0) → distortion.
- **Too quiet overall:** the loud parts stay below about −30 dB → the whole ad is quiet.
- **Holes:** a 0.5 s block far below its neighbours in the middle → a gap in the voice or a dropout.
- **Length:** the audio ends well before the video, or the render's sound is longer than its picture.
- **Music under the voice:** measure the voice part and the music part separately from their `assetUrl` (the VO node, or the clip with speech; the music node). Apply the volumes from the composition (the clip's `volume` × its track's `volume`; a muted track counts as silent), and compare their levels during the spoken lines. The music should sit **15–20 dB under the voice** while someone speaks (20 dB is the accessibility standard for background sound under speech; 15 dB is the usual floor for social ads). Less than 15 dB → "the music may cover the voice at 0:03–0:08", with the volume to set. Rough guide when both tracks are equally loud: volume 0.1 ≈ −20 dB, 0.15 ≈ −16.5 dB, 0.2 ≈ −14 dB, 0.26 ≈ −11.7 dB.
Report sound as measured ("the music sits about 9 dB under the voice, the end stops without a fade"), never as "the sound is fine". Pronunciation, voice quality and lip sync stay questions to the user.
## Step 5. What to look for in the frames
Look only at what is in the frame; compare with the script, the screenshots and the planned text, not with taste.
**Faces**
- the same person in every scene (face shape, hair, age, skin tone) · eyes aligned and alive, looking where the shot says · teeth and mouth natural, not melted · skin real, not waxy · no extra or half faces in the background.
**Hands and fingers**
- five fingers on each visible hand · no merged, extra or missing fingers · the hand touches what it holds (no floating phone or mug) · one phone in one hand, held the way a person holds it (POV inserts: her own hand from the bottom of the frame, nobody opposite).
**Phone screen and logo**
- screen text word by word against the user's screenshot: app name, headings, buttons, numbers · no invented screens or UI that changes between frames of the same shot · the logo and icon exactly as uploaded: shape, colors, letters, not warped or redrawn · a store badge only as the official file.
**Captions**
- never over a face or the mouth (house default under the faces, ~75% of the height; `lyra-video-editor`) · size 80 on 1080×1920, max 2 lines · first word visible at frame 0 · words against the script: the app name, names, numbers, punctuation and ellipses · inside the platform's safe zone.
**Text on images and on screen**
- every letter and number as planned, the app name exactly · no warped, melted or mirrored letters, no gibberish in the background (signs, books, packaging) · nothing extra the plan didn't have · text inside the safe zone, readable at phone size · no fake system buttons (a play button, a close cross, a fake notification or pop-up): platforms reject ads with them; a store-style install button on the end card is fine.
**Safe zones on 9:16 (1080×1920)** for the hook text, the headline, the CTA, the logo and the end card (captions follow the house place in `lyra-video-editor`, not these):
- Reels and Stories (Meta): keep the top ~14% (~270 px) and the sides ~6% (~65 px) clear; the bottom ~35% (~670 px) on Reels, ~14% on Stories.
- TikTok: keep ~130 px top, ~485 px bottom, ~45 px left and ~140 px right clear (the right side holds the like and share buttons).
- These figures change; when in doubt, use the overlay in the Video Editor or the platform's own template.
**Cuts and the edit**
- no black or empty frame · no jump of person, outfit, accessories (jewellery, glasses, a bag), props, light or place where the script has one continuous scene · the end card complete, not cut, the real offer from the Brand Kit, one CTA.
**Severity**, for every problem found:
- **Blocker:** an ad shouldn't run with it (six fingers in a close-up, a wrong app name, a warped logo, captions over the mouth, a wrong price, the voice cut off).
- **Visible:** a viewer may notice (a face drifts between two cuts, bracelets vanish after a cut, a background sign with gibberish, music close to the voice).
- **Minor:** only on a paused frame (a blurry finger in a fast move at the edge).
Unsure whether it is a defect → report it as "please look at 0:07", not as a problem and not as fine.
## Step 6. Report and the fix offer
One message, short, in the user's language, with the problem frames attached as pictures (each picture captioned with its time and problem):
> Checked **14 frames** and the sound of "Calmly · 2 am · 15 s" (start, 6 lines, 5 cuts, the phone shot, the end card). **2 problems:**
> 1. **0:07, scene 3 (kitchen) · blocker:** six fingers on her right hand around the mug, already in the frame before the cut *(picture)*. Fix: simplify the hand and add "five fingers on each hand" to the image "Scene 3: kitchen", rerun the image, clip 3 and the Video Editor, 361 credits.
> 2. **0:11, phone shot · visible:** the button reads "Strat" instead of "Start" *(picture)*. Fix: an insert of the phone screen from your screenshot over 0:10–0:12, 40 credits.
>
> Clean: the same face in every scene, captions under the faces, the end card complete. Sound: no clipping, the voice starts at 0.3 s, the music sits 15 dB under the voice and fades out on the last frame.
> Please listen whether the app name sounds right, and watch 0:04–0:06 at full speed: I check still frames, so a quick morph between them can slip past.
>
> Fix both through lyra-fix for 401 credits?
- **What was checked:** the number of frames, what they covered, and the sound. Never "checked the video" without the count.
- **Each problem:** time (m:ss) · scene or node label · severity · what is wrong, in plain words · its picture · the fix in one line (the cheapest that works, `lyra-fix` Step 2) · its credits from the nodes' `credits` in `get_workflow`.
- **Clean areas:** one line, so the user knows what passed.
- **Questions for the user:** pronunciation and voice (for a video with speech) and motion in any spot that looked suspicious.
- **No problems:** "Checked 14 frames and the sound, nothing broken", plus the pronunciation question. Don't pad the report.
- **The one question:** fix them through `lyra-fix`? The yes hands over to `lyra-fix` with all problems in one fix round (one plan, one cost, one Video Editor render). Nothing is changed or run in this skill.
- **Links** by the base rules: the result checked and the workflow.
## Step 7. Without a browser: the check list
When no browser is available (no Claude in Chrome, no built-in browser, or it can't open the result):
1. Say it in one line: "I can't open the video from here, so here are the moments to look at."
2. Send the frame table from Step 2 as the user's check list: time · scene · what to look at (fingers on the mug, the button text on the phone, captions under her face…).
3. Add the short checks from Step 5 for faces, hands, screen and logo, captions, text, cuts, end card, and the sound questions (music under the voice, a hard stop at the end, the app name).
4. Ask the user to tell you the times where something is wrong (a screenshot is best). Each one they name goes to `lyra-fix` the same way.
The frame table still comes from the edit: Claude reads the composition and the script with the tools even without a browser, so the times are exact. The sound settings (volumes, muted tracks, fades) can be read from the composition too; report them as settings.
---
## Common mistakes (check)
| Mistake | Prevention |
|---|---|
| Says "looks good" without seeing the result | Look in the browser; otherwise the check list |
| Waits to be asked after a final render | Run the check automatically after every final result |
| Takes the render link from `get_run_results` for a render made in another chat | Results drawer in the Video Editor, or ask for the link |
| Random frames, or one frame per clip | Frames from the edit: every line, both sides of every cut, screen and hand moments, start and end card |
| Player controls left on, covering the captions and the end card | `v.controls = false` before every frame |
| Judges fingers and screen letters on the small video in the window | Canvas crops at the video's real pixels |
| Screen text judged by "looks right" | Word by word against the user's screenshot |
| Caption words not compared with the script | App name, numbers, punctuation, ellipses |
| Says the sound is fine | Report what was measured; pronunciation and lip sync are questions |
| Claims there is no morphing | Frames are still; say so and point to the spots to watch |
| Problems described in words only | Attach the crop of each problem frame |
| Invents a problem to have something to report | Only what is in a frame or measured; unsure → "please look at 0:07" |
| Report without times or frame count | "Checked N frames", every problem with m:ss and scene |
| Fixes the problem straight away | One question; the yes goes to `lyra-fix` |
| One fix round per problem | All problems into one `lyra-fix` round, one render |
| Checks in the workflow tab and leaves tabs open | The file in its own tab; close it after |
| Checks only the master, not the cutdowns, sizes or languages | Every version, each reported |
## Quality gates (check)
- **Before the report:** every frame on the list looked at, at full resolution where it matters? The sound measured? Every problem has a time, a scene, a severity, a picture, a fix and its price? Nothing reported that wasn't seen or measured? The pronunciation question and the motion caveat in where they matter?
- **Pass** = the user knows what was checked, what is broken, what it costs to fix, and what is left for them to listen to or watch.
lyra-short-drama76.1 KB
View saved version →
---
name: lyra-short-drama
description: "Short drama video ads for mobile apps in Lyra - a 60 to 120 s mini-series story, animated (3D, 2D anime / storybook / kawaii, stop-motion and knitted worlds) or realistic (live-action sitcom, vertical mini-series, confession), where an underdog hero hits a chain of everyday disasters, meets the app at the turning point or through the plot, and ends happier or more successful, told with in-clip dialogue or a narrator. Offers several story concepts per app from the Brand Kit. Use for \"a short drama ad\", \"a mini-series / story ad\", \"a cartoon story for my app\", \"a realistic story ad\", \"a 1-2 minute story video\", \"drama like ReelShort but for my app\", \"an animated story where the app saves the day\", \"episodes with a cliffhanger\", or a story reference to adapt. Core video rules come from lyra-video-ad-generation."
---
# lyra-short-drama
This skill makes short drama video ads for mobile apps; their goal is installs, trials and subscriptions. A short drama is a 60 to 120 s story that plays like a clip from a mini-series: a hero the viewer roots for, a chain of everyday disasters caused by the pain the app solves, a turning point where the app comes in, and a payoff the viewer can see. It can be stylized (3D animation, 2D, stop-motion), so it reads as AI and as fiction and is still worth watching, or realistic (a live-action sitcom scene, a vertical mini-series, a confession). The skill offers story concepts for the app, writes the chosen story, casts and designs the characters, then builds and runs the whole film in Lyra.
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**App ads first.** Every decision serves one goal: the right person installs the app and keeps using it. A short drama is not a brand film or a cartoon for its own sake; it is a performance ad judged by installs, trials and payers. The story exists to make the audience's pain felt and the app's role believable. If a beat is fun but doesn't move the hero toward the app or show what the app changes, cut it.
**This is a way of thinking, not a script.** The rules below are defaults and good practice. Use judgment: when a different structure, style, length or order serves the story better, do it and say why in one line. Only a few things are fixed: truth (no invented claims, reviews or numbers; the story is fiction and never presented as a real customer), the Brand Kit's facts, Lyra's technical limits, and the user's explicit choices.
**Base skill first.** Everything not written here follows `lyra-video-ad-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, prompt rules, models (Reference A), audio (C), app UI (D), consistency (E), prompt craft (F), errors (G), de-slop (H), Brand Kit (I), Meta app ads (J). This file only adds what is specific to short drama. If the two disagree, the user wins, then this file, then the base skill.
**Other skills it uses.** Openings and opening tests: `lyra-video-hooks` (pain map, hook kinds, hook multiplier). Realistic people, voice anchors and spoken lines: `lyra-ugc-video` (casting, realism, voice, speech rules), with cinematic light instead of phone-real. End card with install button: `lyra-ui-motion-video`. Same story for another audience or market: `lyra-audience-variations`. New pain chain or new angle on a winning drama: `lyra-ad-concept-multiplier`. Remaking a competitor's drama: `lyra-copy-competitor-ad` for the analysis, then this skill for the build.
**Everything comes from the Brand Kit.** The hero, the pain chain, the turning point, the feature, the payoff, the offer, the tone and the look are built from the app's Brand Kit, never from imagination. Source order (base Reference I): the user's words in this chat → the Brand Kit given in the chat → the Brand Kit connected to the workspace or workflow (`list_brand_kits`; one kit → "Make this for {kit name}?", several → ask which) → none: ask once to send it or to connect one of the workspace's kits. Missing facts are asked for or written as hypotheses to confirm, never invented.
**Model.** Characters who talk on screen (3D animation, realistic drama): **Seedance 2.5**, references only, 720p by default (1080p on the user's choice), sound on, up to 30 s per clip. Flat 2D styles (anime, storybook, kawaii, doodle) and stop-motion looks: **Seedance 2.0** (references, or frames when the exact composition matters), 720p by default (1080p on the user's choice), up to 15 s per clip, as in Lyra's own animated story templates. Images: **Nano Banana Pro** for every character sheet and keyframe. Always confirm with `list_node_configs` and ask the user's preference in the plan (base Reference A).
---
## How to think about short drama
**What it is.** A short film in the language of vertical mini-series (ReelShort, DramaBox style), adapted for an app: conflict in the first seconds, quick escalation, a turn, an emotional payoff, a CTA. It works because the viewer starts watching a story, not an ad: the skip reflex doesn't fire, curiosity and empathy carry them past the point where a normal ad loses them, and by the time the app appears they already want the hero to win. The app is the hero's tool, not the hero.
**Animated or realistic.** Animation tells the viewer at once "this is a story", so nobody mistakes it for a testimonial; it hides the small imperfections that make AI people uncanny; it keeps characters consistent more easily across 60 to 120 s; and exaggerated acting reads with the sound off. Realistic drama feels closer to the viewer's own life and to the drama apps' own ads; it needs more care on faces, a clear fiction frame and the AI label (see Realistic drama). Choose by audience and category (see Category guide), and test both on the same script when unsure.
**Four pillars, all built from the audience's pain:**
| Pillar | Question it answers | Comes from |
|---|---|---|
| **Hero** | Who do we root for, and why do they deserve a win? | the audience segment in the Brand Kit, as an underdog |
| **Pain chain** | How does the pain ruin the hero's day, week, relationships? | the pain map, turned into 3 to 6 concrete scenes |
| **Turn** | Who or what brings the app into the story, and what exactly does it do? | one real feature, one messenger or plot device, an honest time to result |
| **Payoff** | What is visibly different now, and who notices? | desires and outcomes from the Brand Kit, mirrored on the pain scenes |
All four tell one story. A dog owner whose untrained puppy ruins her morning, her job, her neighbour's patience and her dinner party; a friend with a calm dog shows her the training app; "Day 14"; the same places, the same people, now going right; a stranger says "yours is so calm". That is one idea. A generic "sad person, downloads app, happy person" is not a story, it's a slide.
**Final test for every concept:** can the logline be said in one sentence with a hero, a pain, a turn and a payoff? Would the right viewer recognise their own life in the pain chain? Does the payoff show what the app really does, at a believable speed? Would a viewer who leaves after 10 s still know which app this was about? Would you watch the next scene even if it weren't an ad?
**Principles:**
- **Conflict in 3 s.** Open at the peak of a disaster, mid-scene, never on an establishing shot or a logo.
- **Every scene escalates.** Each disaster costs more than the last: time → money → face → a relationship. Same pain, new arena.
- **Every disaster has a witness.** The boss, the neighbour, the partner, the guests: their one line is the social cost, and the person the hero wants to win back.
- **Most viewers never reach the end, so the app can't wait for it.** Plant a light brand thread early, bring the turn at about 35 to 55% of the runtime (up to ~60% in a 2 min film), never in the last third (see The app in the story).
- **The app moves the plot.** It arrives through a person who shows their own result, or it causes the next event. A forced insert ("and now a word about our app") breaks the story and the trust.
- **Time is honest.** A title card ("Day 14", "Three weeks later") matches the Brand Kit's real time to result. No instant magic.
- **The payoff mirrors the pain.** The same places and people from the pain chain, now going right; the witness who complained now compliments. This is the satisfying click, and it reuses the sets (cheaper and more consistent).
- **One hero, one pain, one feature.** A second feature is a second episode.
- **Show, don't tell.** Expressions and actions carry the story; dialogue is short; it all reads muted with captions.
- **Warmth and a little humour.** Dramas for apps win on relatable comedy and sympathy, not on misery.
- **Modular scenes.** Every scene stands on its own, so the same film cuts down to 59 s, 30 s and a teaser without new generation.
---
## Why it works, and why it should work for us
**What research and platform data say** (numbers are from the named studies; vendor and platform data marked):
- **Being carried into a story changes minds.** A meta-analysis of 76 studies (van Laer et al., Journal of Consumer Research, 2014) found that narrative transportation goes with stronger emotions (ρ ≈ .57), attitudes (≈ .44) and intentions (≈ .31). Transportation grows with a plot that's easy to picture, realism, and a hero the viewer identifies with. → Concrete scenes from the audience's life, a hero from the audience.
- **Underdogs sell.** Underdog stories (a disadvantage plus passion and determination) raised purchase intent and choice through identification (Paharia et al., JCR, 2011). → The hero is losing but trying, never pathetic.
- **Arcs that end high get engagement.** In an MIT Media Lab × McKinsey study of ~1,500 short films, arcs that end on a big positive spike, especially after ups and downs, drew the most engagement. → Pain chain, rock bottom, payoff.
- **Brand inside the story pays.** Kantar × Meta × CreativeX (57k Meta assets, 2024): integrating the brand into the story added ~46% effectiveness, but only ~36% of campaigns did it well; fast storytelling (4 scenes in 6 s) +73%; people and eye contact +81% [platform research]. → Integration levels, fast cold opens, faces.
- **Storytelling beats tactical.** TikTok × Dentsu (MMM, 15 Nordic brands, 2025): storytelling UGC had ~70% higher ROI than tactical UGC [platform data].
- **It looks like content.** Drama-style ads don't look like ads, so they get past banner blindness; actors overplay so the plot reads muted (Palai Media).
**What to be careful about:**
- **Long ads are watched briefly by most.** In an agency analysis of 421 Meta ads (Biddy Co, 2026), cost per result was about the same at every length, 60 s+ included, but average watch time was ~3 s and only ~0.2% of impressions reached the end [agency data]. The full film works for the minority who get hooked (they are the high-intent ones); everyone else must get the hook, the app and the promise early. This is why the skill puts a brand thread early, the turn before the last third, and always makes cutdowns.
- **Cliffhangers are not magic.** A lab study (Wirz et al., 2023) found cliffhangers raise arousal but not the intention to keep watching. Every episode must sell on its own.
- **Fatigue is fast.** The format burns out quickly; one Chinese brand that pioneered brand dramas saw results fall sharply once everyone copied it. Plan variants from the start.
- **ROI is not proven for every category.** Public performance data for non-drama apps is scarce; treat each drama as a test against your best UGC.
**Why it should work for us (Lyra and its clients):**
- **Live action is the barrier.** A live-action vertical series costs about $130k to 300k and a drama ad set $1.5k to 3k [industry reports]; AI production is reported at 1/5 to 1/10 of that [vendor data]. Most app marketers can't shoot dramas; they can build them in Lyra.
- **The format needs volume.** Drama advertisers ran ~1,900 creatives per app in H1 2026, more than any other category [vendor data]. The winners run a system, not one film: Woofz runs many 3D dramas of 84 to 244 s with different heroes, dogs and languages. Lyra makes the system cheap: one cast and world, many pain chains, heroes, languages and cutdowns as variations.
- **Consistency is the hard part, and it's what the graph solves.** Character sheets as references, keyframes chained from them, Seedance 2.5 clips up to 30 s with dialogue, one canvas per film with variations.
- **It's still fresh outside drama and games.** In our scan most non-drama apps still run 10 to 60 s skits; long story ads are a way to stand out in the feed (an observation, not a guarantee).
---
## What the market shows
Examples seen in Meta Ad Library (Oct 2026) and public sources. Timings approximate.
| Advertiser | Category | Style, length | Story | How the app comes in | Lesson |
|---|---|---|---|---|---|
| **Woofz** (the reference) | dog training | 3D, ~126 s | a heroine's day of disasters with clock chapters (7:15 → 20:15) | a friend with a calm dog names the app and a named course at ~55%; "Day 14"; witness reversal | the full template (teardown below) |
| **Woofz** (second film) | dog training | 3D, ~141 s | a young man and his rottweiler puppy: "I've watched a bunch of YouTube videos" → "Maybe getting him was a mistake" → "I can't afford K9 training" → a family BBQ he's told not to come to | an older pet-shop expert shows the app on a tablet: the same method at home, no trainer needed; payoff: accepted at the BBQ | an expert messenger; the price objection answered inside the drama |
| **Woofz** (the system) | dog training | 3D, 84 to 244 s | many heroes (men, women, older owners), breeds, settings; English, Spanish, Portuguese, German; karaoke captions | the same turn mechanics | one world, many heroes and pains: a drama system |
| **Praktika** | language learning | realistic, 100 to 140 s, Brazilian Portuguese | on a plane with a foreign passenger; at home cooking while talking with the AI tutor on a tablet | a flight attendant asks "Já ouviu falar do Praktika?" at ~30%; then the app is used inside the scenes | an early messenger; the app as a plot device; two ads share one opener and test different bodies |
| **BetterMe: Mental Health** | mental health | photoreal AI, 74 s, "Generative AI used" in frame | a woman on a panel: "It took me getting divorced at 35 to realize I wasn't hard to love, I was hard to stay with" | late, as the way she understood her patterns | the confession format; the twist is the first line; in-frame AI disclosure |
| **Finch** | self-care | text-post story, 91 s | "I can't tell my wife the real reason I've been cleaning the house" → his daughter put a cartoon-bird app on his phone | the app is the secret | the "secret" structure; a story without video generation (careful: see Truth and safety) |
| **Calm** | mental health | illustrated, ~51 s | a stressed mother, a crying child; "nervous systems, not bad parenting" | the app never on screen, only headphones and the CTA | soft framing for delicate topics |
| **Rocket Money** | finance | live skit, 37 to 60 s | guess your subscriptions → the reveal | the app is the twist | the reveal mechanic |
| **Duolingo** | education | anime series, 5 × 60 s; the "Duo is dead" arc | a mascot world | the product mechanic is the plot (earn XP to bring Duo back) | a mascot as a character; a plot people take part in |
| **Brand dramas in China and India** (Meituan, Pupu, Taobao, Zomato, Myntra) | delivery, e-commerce | live-action series | the app saves a family dinner, a party, a job | from prop placement to a fully custom plot | the integration ladder; forced inserts and overuse kill results |
**Take the mechanism, never the material:** no competitor's characters, lines, sets, look or music in our films (base Reference B); these examples teach structure only.
**What to take from it:** dramas for apps run as systems (many heroes, pains, languages), the app comes earlier than the drama apps' own cliffhangers would suggest (30 to 60%), the messenger is either a peer with visible proof or an expert who removes an objection, realistic and animated both work, and disclosure travels with realistic AI people.
## Reference teardown: the dog training app drama
The reference the team started from (Meta Ad Library, Woofz, active from 22 Sep 2026, ~126 s). Timings approximate, from frames.
| Time | Beat | What happens | Why it works |
|---|---|---|---|
| 0 to 3 s | **Cold open, chapter "7:15"** | The heroine (red hair, glasses, mustard shirt) stands soaked in the bathroom; the poodle runs out | conflict at frame 1; a clock as chapter marker promises "a day" story |
| ~4 to 8 s | **"7:25"** | A puddle in the hallway, the poodle sits "innocently", she enters frame | escalation, comedy, the pain is the dog's behaviour, not the dog |
| ~9 to 14 s | **"8:47" office** | Late, dishevelled; a coworker looks; she: "Is it that obvious?" | the pain leaks into work; a witness |
| ~20 to 26 s | **"18:30" stairwell** | The dog pulls on the leash; the elderly neighbour: "...have to complain" | social cost rises |
| ~32 to 38 s | **"19:05" dinner** | Her partner: "They're all like that" | the home witness gives up on the problem |
| ~45 to 52 s | **"19:40" guests** | The dog jumps on guests; she: "He's just excited" | public embarrassment, the peak |
| ~59 s | **"20:15" rock bottom** | On the sofa, hugging the dog, sad; the partner looks at her | a quiet beat, empathy |
| ~66 to 73 s | **The turn** | In the park, a friend with a calm dog: "I downloaded [app] and started [named course]" | the messenger's calm dog is the proof; the app named with a real course |
| ~80 s | **"Day 14"** | Black title card | honest time jump |
| ~87 to 100 s | **Payoff** | The poodle sits calmly, brings the leash; a calm walk out of the same hallway | mirror of the 7:25 hallway |
| ~106 s | **Witness reversal** | Another owner (whose dog misbehaves) says: "Yours is so calm" | the heroine is now the friend with the calm dog |
| ~112 s | **Button** | She holds the phone (app icon screen) to camera: "Best thing that ever happened to us" | the app's identity, one warm line |
| ~113 to 126 s | **End card** | "TRY NOW" button on a paw pattern | CTA; held ~13 s, longer than needed |
Style: soft stylized 3D animation, big expressive eyes, warm interior light, detailed lived-in sets, one signature outfit for the heroine the whole film. Dialogue spoken in the clips; captions burnt in post; the clock and "Day 14" as text in post. The ad's post copy above the video names the app and lists its features from second 0. What to keep: chapter markers, witnesses, the messenger, the honest time jump, the mirror payoff, the witness reversal. What to improve: an earlier brand thread, the app's real feature visible once, a tighter Act 1, a 2 to 4 s end card.
---
## Step 1 additions: from the Brand Kit to the pain chain
1. **Brand Kit and pain map.** Read the Brand Kit (base Reference I). Build the pain map as in `lyra-video-hooks` Step 1 (audience, pains in their words, desires, objections, product truth); reuse it if one exists for this app. Find the app's row in the Category guide.
2. **The hero.** One person from the audience segment, made specific and lovable: name, age, job or life stage, one quirk, one want ("Mia, 29, junior designer, first dog, wants to be the calm, together person she pretends to be"). The hero is an underdog: likeable, trying, losing, never stupid or pathetic.
3. **The pain chain.** 3 to 6 concrete situations where the pain costs the hero something, in rising order, each with a place, a time marker and a witness. Example (fictional sleep app Calmly): 02:47 awake, scrolling, partner sighs · 07:58 oversleeps, coffee on her shirt · 10:30 falls asleep in the client meeting, boss stares · 18:40 snaps at her sister on the phone · 23:55 awake again, crying quietly.
4. **The old way.** What the hero already tried and why it failed (YouTube videos, willpower, a spreadsheet, an expensive trainer): it makes the app's difference concrete and can carry an objection ("I can't afford a trainer").
5. **The turn.** Who or what brings the app (a peer with visible proof, an expert, a stranger, the plot itself), what they say, the one feature by its real Brand Kit name, the integration level (see The app in the story), and the honest time to result.
6. **The payoff.** The same situations, now going right, and the witness reversal (the person who sighed, stared or complained notices). Only results the Brand Kit can stand behind.
7. **Intake quiz** (base Step 1: one message, multiple choice, options from the Brand Kit, the recommended option first, 4–8 questions; skip what the task or the kit already answers), with these questions plus the base quiz questions that apply:
- Visual style: animated or realistic (offer 2 to 3 from the Style library with a recommendation), or "you decide".
- Length: 60 to 90 s (default) or 2 min; one film or a series of episodes.
- Voice: dialogue spoken in the clips, a narrator, or both (see Dialogue and narration).
- Language and market.
- The app logo and 1 to 3 screenshots (the turn and the button show the app; screenshots only, never a screen recording).
- Approved claims, forbidden claims, the honest time to result (above all for health, money, kids and pet apps).
- The hero: any preference on age, gender, family, pet, job; or "you decide" from the audience.
**Defaults (state, don't ask):** cold traffic · Instagram Reels / TikTok · 9:16 · **75 s** (60 to 90; 2 min on request) · always a **59 s cut** too (per Meta's specs at the time of writing, videos over 60 s lose Facebook Reels ads and in-stream placements, and over 2 min Facebook and Messenger Stories; Instagram Reels and TikTok take long videos; the media buyer checks in Ads Manager) · one complete story (series on request) · **3D animation** style · dialogue spoken in the clips, captions added in the Video Editor · English · one score for the whole film with an emotional arc, instrumental · chapter markers on screen (added in post) · app logo screen on the phone at the turn and the button · end card 2 to 4 s · Seedance 2.5, references, 720p (1080p on the user's choice), sound on · Nano Banana Pro 2K, 9:16 for every image.
**Recommended first run:** A1. Cast (the characters and the look decide everything; images are cheap), then A2. Keyframes after the user selects the sheets, then B. a pilot clip before the rest.
## Step 2 addition: concepts, then the drama concept card
**Offer three different concepts first.** Unless the user brought a fixed story, write **3 short concept options** that differ in structure, style and how the app comes in (e.g. A: a 3D day of disasters with a friend as messenger · B: a realistic comeback where the app is used inside the scenes · C: a storybook fable with a narrator), 3 lines each (logline · style · how the app comes in), with one recommended and why for this audience. The picked one becomes the concept card. Two concepts can be built for a test.
The concept the user approves (base Step 2) is a drama concept card per film:
> **D1 · "Running on Empty" · 3D animation · 75 s (+59 s, 30 s cuts) · dialogue + captions**
> Logline: a sleepless junior designer wrecks her own week until a coworker shows her the five-minute wind-down that finally lets her sleep.
> Hero: Mia, 29, junior designer, dark curly hair in a low ponytail, sage-green overshirt over a white tee · Cast: Leo (partner), Dana (boss), Jess (coworker, the messenger).
> Hook: cold open at 10:30, Mia asleep on the client's slides, Dana: "Are we… boring you?" Then a card "8 hours earlier" and the chain runs forward.
> Brand thread: in the cold open, Jess's phone lies face-up on the meeting table showing the Calmly logo screen (from the user's logo) for under a second; nobody comments.
> Pain chain: 02:47 awake, Leo sighs · 07:58 coffee on her shirt · back to 10:30, Dana's stare · 23:55 crying quietly in the kitchen.
> Turn (~45%): Jess at the coffee machine, fresh and calm: "Five minutes of Calmly's wind-down. Every night. That's it." (L2, peer messenger)
> Time jump: "Night 7" card.
> Payoff: 23:00 asleep with the timer on · 07:00 awake before the alarm · 10:30 Mia presents, Dana nods: "Great work." Leo: "You're… humming?"
> Button: Mia to camera, phone with the Calmly icon: "Turns out I just needed to switch off." End card: logo + "Free for 7 days".
> Clips: 5 × Seedance 2.5 · cold open (~9 s, the pilot) · night and morning (~20 s) · turn (~10 s) · payoff (~22 s) · button (~6 s) · music: tense-comic → quiet → warm → bright · ~110 spoken words · ad copy for Ads Manager in the script node.
The hook gets 3 to 5 options (see Openings); the plan recommends one. For a series, one card per episode and a series line (see Series option).
---
## Category guide
Starting points, not rules; the Brand Kit decides. "Seen" = we saw this category run story ads; "judgment" = our recommendation without a market example yet.
| Category | Hero and pain chain | Turn and integration | Style | Careful with | Evidence |
|---|---|---|---|---|---|
| **Pets, training** | first-time owner; mess, chewed things, pulling leash, neighbour, guests, landlord | peer with a calm pet or an ex-trainer; the price objection ("can't afford a trainer"); L2 | 3D (warm, comic) | never hurt or scare the animal; no guaranteed behaviour in N days | seen: Woofz |
| **Language learning** | traveller, expat, professional; freezes with a foreigner, a job interview, the partner's parents, a waiter | a stranger or colleague asks "heard of…?"; then the hero practises inside the scenes (AI tutor, lesson on the commute); L2 + L3 | realistic sitcom, or 3D | no fluency in days; real accents, no mockery of accents | seen: Praktika |
| **Mental health, self-care, journaling** | overwhelmed adult; bed rot, snapping at people, the same relationship pattern again | a friend, a partner, the hero's own discovery; the app as the quiet secret; L2 soft, L4 if the brand has a mascot | storybook, kawaii, knitted; or a realistic confession | no clinical crisis, self-harm or diagnosis talk; no "cures"; soft framing | seen: BetterMe Mental Health, Finch, Calm |
| **Sleep, meditation** | tired worker or parent; night scrolling, oversleeping, falling asleep in the meeting | peer with visible rest; L2 | storybook, 3D | no insomnia cure | judgment |
| **Fitness, workouts, steps** | busy parent, gym newbie; out of breath on the stairs with kids, skipped workouts, can't keep up on a hike | friend a step ahead, a coach character; L2 / L3 (a 10-minute session in the living room) | 3D, realistic | the payoff is energy and confidence, not the body; no body shaming, no kg by a date, no body before / after | judgment (most fitness apps run short skits) |
| **Finance, budgeting, saving** | young professional; card declined on a date, surprise subscriptions, rent panic, money gone by the 15th | the app reveals the leak (twist, L3) or a peer with money left (L2) | realistic, 3D | no guaranteed savings or returns; staged numbers clearly fictional; no mocking debt | seen: Rocket Money (skits) |
| **Dating** | serial bad dates, ghosting, the friend's wedding alone | the app is how they meet (L3) | realistic, 3D, anime | non-sexual; no humiliation of a gender; no guaranteed love; no fake matches | seen: Hinge skits, Tinder's interactive series |
| **Books, self-growth, brain training** | stuck professional; doomscrolling, silent in the meeting, passed over for promotion | 15 minutes a day; the bad habit personified as a villain; L2 / L4 | 3D, 2D | no income or career promises | seen: Headway's "Mr. Procrastinator" (2023) |
| **Productivity, planning, to-do** | parent or student; missed deadlines, the forgotten pick-up, 47 tabs | the app plans the day inside the scenes; L3 | 3D, realistic sitcom | no invented time saved | judgment |
| **Parenting, kids, family** | parent; homework fights, screen-time battles, bedtime chaos | another parent; L2 | storybook, 3D | kids never endangered or in distress for the plot; no blaming parents; no claims about children's results | judgment |
| **AI photo, video, creative tools** | small business owner, creator; bad photos, lost sales, hours of editing | the app's output changes the next scene (L3) | realistic, 3D | the output shown only from real results | judgment |
| **Health tracking, women's health, nutrition** | an unclear pattern, a doctor visit, meal chaos | peer or the hero's own discovery; L2 | storybook, 3D | claims only from the Brand Kit; no diagnosis | judgment |
| **E-commerce, delivery, grocery** | the party, the gift, the family dinner about to fail | the app saves the day (L3), or placement through the story (L1) | realistic, 3D | real prices and delivery times only | seen: brand dramas in China and India, Temu skits |
| **Utilities (VPN, cleaner, caller ID, scanner)** | full phone at the kid's recital, a scam call, the lost document | the app as the fix in the moment (L3) | realistic, 3D comic | no fear-mongering, no fake system alerts or OS UI | judgment |
---
## Story structures
A reference, not a menu. Pick from the pain and the audience; combine.
| Structure | Shape | Best for | Example |
|---|---|---|---|
| **A day (or week) of disasters** (default) | clock or day chapters → rock bottom → messenger → "Day N" → mirror payoff | daily-habit pains: pets, sleep, productivity, kids, money | the dog training reference |
| **Underdog comeback** | humiliation in front of someone → app → triumphant return to the same place | learning, fitness, career, language, confidence | laughed at for bad Spanish at a dinner → app → orders for everyone in Madrid |
| **Expert mentor** | the hero tries the old way and fails → an expert (trainer, teacher, coach character) sees it → the app as the affordable, at-home version of the expert | categories with a paid human alternative | the pet-shop expert in Woofz's second film |
| **Two timelines** | split or alternating "without the app / with the app" days | utilities, planning, finance | same Monday, two versions |
| **The secret** | the hero has changed and hides why, or notices someone who has it together and investigates; the app is the reveal | habits, self-care, money, beauty | Finch: "the real reason I've been cleaning the house" |
| **Confession** | one person tells their story to an audience (a panel, a podcast, a friend), the twist in the first line, cutaways to the past | mental health, relationships, money; realistic style | BetterMe: "It took me getting divorced at 35…" |
| **Relationship drama** | the pain strains a relationship (partner, parent, boss, roommate) → the app removes the friction → reconciliation | family, couples, shared money, home, health habits | the fight about the bills, settled |
| **Fail and rewind** | the hero makes the wrong move, disaster, the scene rewinds, the app path shows what goes right (borrowed from game "fail ads") | utilities, finance, learning | the scam call, rewound |
| **Rival** | a rival seems to win; the hero turns it around with the app (light, never cruel) | competitive categories, fitness | the gym "mirror guy" |
| **Fable** | animals, mascots or objects live the human pain in a small world | kawaii, storybook, knitted styles; broad or young audiences; delicate topics | the kitten who spent everything on skincare (Lyra template) |
| **Cliffhanger episode** | stops after the turn, before the payoff; the next episode resolves | series option, retargeting | "…and then Jess showed me her phone." |
**Short drama tropes, made app-safe.** Drama apps sell betrayal, revenge, hidden identity and the big comeback (betrayal, revenge, forbidden romance skew to women; hidden identity and comebacks to men, per trend reports). Use their energy, not their content: betrayal → "my own habits betrayed me" or a friend who kept the secret; revenge → the comeback in front of whoever doubted; hidden identity → "nobody knew I was the one who…"; romance → the date that went wrong because of the pain. No cheating, violence, abuse, humiliation of a group or anything the brand wouldn't put its name on (brand safety, base Reference B).
## Beat sheet
**75 s default (60 to 90 s):**
| Beat | Time | What happens | Rule |
|---|---|---|---|
| **Cold open** | 0 to 3 s | the most painful or funny moment of the chain, mid-action, first line or sound | conflict at frame 1; built with `lyra-video-hooks` |
| **Pain chain** | 3 to 28 s | 3 scenes, 6 to 8 s each, a chapter marker on each, each ends on a witness reaction; a light brand thread in one of them | escalate; one location per scene; no dead air |
| **Rock bottom** | 28 to 33 s | one quiet beat: alone, the cost lands | the only slow beat before the turn; music drops |
| **Turn** | 33 to 42 s | the messenger and their proof (or the plot device), the app named once, the one feature in one line, the phone shown | 35 to 55% of the runtime |
| **Time jump** | 42 to 44 s | title card "Day 14" / "Night 7" / "Three weeks later" | honest, from the Brand Kit |
| **Payoff** | 44 to 64 s | 2 to 3 mirror scenes in the same places, the witness reversal | show the result in life, not on a screen |
| **Button** | 64 to 72 s | the hero to camera (or to the witness), phone with the app icon, one warm line | not ad copy |
| **End card** | 72 to 75 s | logo, the real offer, install button | 2 to 4 s |
**A cold open taken from the middle of the chain** (the meeting at 10:30) is followed by a time card ("8 hours earlier") and the chain runs forward from there, or the chain simply continues forward from the cold open. Never jump back without a card.
**2 min:** the same shape, longer: pain chain of 5 to 6 scenes (an old-way attempt and an objection among them), a short subplot (the partner's patience running out), a payoff of 3 to 4 mirror scenes, the turn at ~45 to 70 s (never past ~60%).
**59 to 60 s:** pain chain of 2 to 3 scenes, payoff of 2, the turn at ~22 to 28 s.
**Cutdowns.** One drama gives four ads: the full film, a **59 s cut** (drop one pain scene and one mirror scene, end card 2 s), a **30 s cut** (cold open, 1 pain scene, turn, 1 payoff, end card ≈ 3 + 7 + 9 + 7 + 3 s) and a **10 to 15 s teaser** (the cold open, one beat of the turn, the end card). Cut only at scene boundaries: write each scene's start and end second inside each clip in the script. Each cut is its own Video Editor (no credits) with its own short music node (cheap) or the score trimmed with a fade; captions follow the clips.
---
## The app in the story
**Integration levels.** Pick one main level (L2 or L3 in most films) and add an L1 brand thread.
| Level | What it is | Use when | Example |
|---|---|---|---|
| **L1 Brand thread** | the app appears in passing before the turn, under 1 s, only as the real logo screen or a real screenshot: the messenger's phone face-up on a table, a tablet in the background | almost always; it plants recall for viewers who leave early | Jess's phone on the meeting table in the cold open |
| **L2 Messenger turn** (default) | a person shows their own result and names the app with one feature | most categories | the friend with the calm dog; the pet-shop expert |
| **L3 Plot device** | the app causes the next event or is used on screen in life | language, dating, finance, AI tools, delivery, productivity | they meet on the app; he talks with the AI tutor while cooking; the subscriptions reveal |
| **L4 The app as a character** | the brand's mascot lives in the story | only when the Brand Kit has a mascot; never invent one without the user | Finch's bird, Duolingo's owl |
| **L5 End card only** | pure story, the app only at the end | teasers and brand content; weakest for performance | — |
**Rules:**
- **On Meta and TikTok the advertiser name and the post copy sit above the video from second 0.** The film can stay story-first; the post copy carries the app name and the offer (see Ad copy).
- **The messenger shows proof.** Their result is visible in the scene (the calm dog, the fresh face, the money left) before they name the app. An expert messenger removes an objection (price, time, "I tried videos").
- **The app moves the plot.** If the scene would play the same without the app, it is a forced insert: rewrite it.
- **The phone moment.** At the brand thread, the turn and the button, the phone screen shows the **app icon / logo screen** (the user's logo on the brand color) or the user's real screenshot, made as a phone image with the logo or screenshot connected as reference, in the film's style (base Reference D). **One phone image per phone that appears** (the messenger's, the hero's), each connected as a reference to the clip where it appears. No notifications, lock screens or OS UI. Check every screen letter by letter; if it breaks, turn the screen away in the clip and lay a short UI insert or the logo screen over it in the Video Editor.
- **No logo and no screenshots:** the screen stays turned away, the app is named in the line and in the caption, and the end card waits for the logo (ask for it before the final run).
- **Never invented UI,** never a full walkthrough; one screen or the logo is enough in a drama. An AI tutor or chat on a screen is shown only from real screenshots, or as a voice the hero answers with the screen turned away.
- **The feature is a line, the result is a scene.** "She started the small dog course" (line) → "the dog brings her the leash" (scene).
- **The end card** is the app's real identity: logo, the real offer ("Free for 7 days"), an install button; made with `lyra-ui-motion-video` or uploaded by the user; 2 to 4 s.
---
## Style library
Pick one style per film and hold it to the last frame. The style is written once as a **style anchor** in the script and repeated word for word in every image and clip prompt.
| Style | Style anchor (write the look, not a studio name) | Best for | Video model | Watch out |
|---|---|---|---|---|
| **3D animation** (default) | "stylized 3D animated feature film look, soft rounded character design, big expressive eyes, subtle subsurface skin, warm global illumination, detailed lived-in sets, gentle depth of field, rich but soft colors" | most apps; wide audiences; dialogue | Seedance 2.5 refs | drift toward photoreal faces; plastic toy look; too dark interiors |
| **2D anime** | "2D anime style, clean thin lineart, cel shading with two-tone shadows, expressive eyes, painted backgrounds, soft light bloom" | Gen Z, learning, dating, games-adjacent, wellness | Seedance 2.0 refs (frames for exact shots) | lip-sync weak in flat 2D: short lines or narrator; line wobble |
| **Storybook watercolor** | "children's picture book illustration, delicate hand-drawn linework, watercolor and colored pencil textures, muted pastel palette, cozy light" | calm, learning, kids and family, wellness | Seedance 2.0 refs | stays static; narrator works best; keep scenes simple |
| **Kawaii doodle** | "ultra-simple Korean kawaii doodle, thick clean black outlines, rounded blob shapes, flat pastel colors, almost no shading, sticker style" | fables with animals or mascots; finance, beauty and habit apps for young audiences | Seedance 2.0 refs | very simple faces: emotion through posture, tears, props; music + narrator |
| **Stop-motion / knitted / clay / felt** | "fully knitted miniature world, visible stitches, tactile yarn, macro photography, shallow depth of field, warm 35mm look, subtle stop-motion feel" (or clay / felt) | emotional and wellness apps, premium feel, delicate topics | Seedance 2.0 (frames or refs) or 2.5 refs | scale errors (a giant phone); the material changes between shots |
| **Realistic: sitcom / real life** | "naturalistic real-life scene, handheld or locked-off camera, available light, real lived-in locations, natural skin texture, unpolished, natural comic timing" | language, utilities, productivity, delivery; audiences that skip polished ads | Seedance 2.5 refs | uncanny faces; overacting; see Realistic drama |
| **Realistic: vertical mini-series** | "vertical mini-series look, cinematic soft key light, motivated practical lights, shallow but readable depth, faces filling the frame, natural skin texture" | money, career, relationships, dating; audiences that live in drama apps | Seedance 2.5 refs | identity drift; melodrama tipping into parody; AI label |
| **Realistic: confession** | "one person telling their story to an audience, stage or studio light, intimate close-ups, cutaways to the past" | mental health, relationships, money | Seedance 2.5 refs | must stay clearly a dramatization; AI label |
| **Motion comic** (budget) | the chosen 2D style as illustrated panels, camera moves across each image, narrator | tight budget, a story test before a full build | Seedance 2.0 Fast or 2.0 (frames), slow push-ins | feels cheap if the story is weak; for story tests |
**Style rules:**
- **No studio, franchise or artist names** in prompts and never a known character or a lookalike. Describe the look (shapes, lines, shading, light, palette, textures). It keeps the style ours, keeps the models from refusing, and keeps the brand safe.
- **The Brand Kit's palette sets the world.** One dominant color family from the brand, kept in sets and the hero's outfit; the payoff can be a little brighter and warmer than the pain chain (the light change is part of the story).
- **Style drift is the main risk in a long film.** The style anchor goes first in every prompt, the character sheet is a reference in every image and clip, one image model and one video model for the whole film.
- **Choose with the user.** Offer 2 to 3 styles with one line each and a recommendation tied to the audience and category. A strong test set for one story is the same script in an animated and a realistic style.
## Realistic drama
Three flavours, all on Seedance 2.5 with references, all built with the realism rules of `lyra-ugc-video` (real skin, lived-in places, casting from the audience, never "flawless") but with motivated cinematic light instead of phone-real.
| Flavour | Looks like | Writing | Camera and acting |
|---|---|---|---|
| **Sitcom / real life** (Praktika-like) | an overheard real situation: a plane, a kitchen, an office | situational comedy; a stranger or colleague starts the turn early; the app used inside later scenes | handheld or locked-off, eye level; natural acting with comic timing; real ambience |
| **Vertical mini-series** (ReelShort-like) | a heightened soap: faces fill the frame, reaction close-ups, a big reveal | high-concept first line, a reveal, a reversal; the comeback | close-ups and reaction beats written into the script; rack focus; end each scene on the most surprised face, not on the reveal itself; acting heightened but not parody |
| **Confession** (BetterMe-like) | one person telling an audience what changed their life | the twist in the first line; short past flashes; the app as the moment they understood | a stage, a podcast set or a sofa; close-ups and listeners' reactions; one speaker |
**Craft rules for realistic AI drama** (practitioner tips):
- 1 to 2 short sentences per shot; on a longer line, cut away from the mouth to a listener or a detail.
- One camera axis per dialogue exchange: reverse angles make backgrounds drift; a new location is safer than a new angle.
- Frame above the hands when you can; hands are the most visible AI tell.
- Layer room tone and ambience under every line; silence exposes AI voices.
- Same signature wardrobe through the film; a change of outfit only with a new character image.
- **Fiction frame:** the characters never claim to be real customers. Confession-style lines ("I used this app and…") are a dramatization: say so (see Truth and safety). The AI label goes on; for the EU, a small in-frame "AI-generated" note is the safe default for realistic people (the BetterMe ad does this).
---
## Cast: characters and consistency
A 60 to 120 s film is 3 to 8 clips on Seedance 2.5, 6 to 15 on Seedance 2.0; holding the same faces through all of them is the hardest technical part. Consistency comes only from images connected as references and anchors repeated in prompts (base Reference E), never from a text node.
**Character card.** For every character, written once in the script node and repeated word for word in every prompt where they appear:
> Mia (hero) · 29 · junior designer · warm olive skin, a few freckles, dark curly hair in a low ponytail, small gold hoop earrings · sage-green overshirt over a white tee, dark jeans, white sneakers · expressive, clumsy, kind · voice: young woman, late 20s, warm American accent, a little breathless when stressed
**Signature outfit.** One outfit per character for the whole film (cartoon logic, and it helps the model hold identity). Change it only when the story needs it (pyjamas at night), and then make a second character image from the first.
**Cast size.** The hero plus 2 to 4 side characters (the witnesses and the messenger). Pets and mascots count as characters and get their own sheet. A witness who appears once can stay unnamed but still gets a one-line card ("the neighbour: woman, 70s, grey bob, lilac cardigan, slippers").
**Character sheet images (stage 1):** one Nano Banana Pro image per character, 9:16, 2K, count 2 (the user picks one): full body, front three-quarter view, neutral pose, plain soft background, the style anchor and the card word for word. For the hero of a long film, a second sheet with a close-up of the face (and, for realistic drama, a profile) helps hold identity across angles. These are the references for every keyframe and clip.
**Location keyframes:** one image per scene, made **with the character sheets as input images** ("Use the exact characters from the reference images… new scene: …"), so face, outfit and style carry over (as Lyra's own story templates chain their scene images). One keyframe per place is enough when several scenes happen there; mirror scenes in the payoff reuse the pain chain's keyframe, changed by light and props ("the same hallway, morning sun, the puddle gone, the dog sitting calmly").
**References per clip:** a small, purposeful set: the characters in the clip + the location keyframe(s), usually 2 to 4. Assign each in the prompt: "[Image1] is Mia… [Image2] is Leo… [Image3] is the kitchen at night". Never connect the whole cast to every clip.
**Voices:** one voice anchor per character in the card, word for word in every clip where they speak; one narrator voice for the whole film.
**What hides drift between clips:** chapter cards and title cards between scenes, cuts on action, a cut to a reaction or a detail (the dog's paws, the coffee stain), and the stylized look itself. Plan these cuts in the script.
---
## Dialogue and narration
Three modes; pick in the plan, by style and by what the user prefers. **No mode ever generates text in the clip:** every clip prompt says "no subtitles, no captions, no on-screen text"; captions, chapter markers and title cards are added in the Video Editor.
| Mode | How | Best for | Watch out |
|---|---|---|---|
| **A. Dialogue in the clip** (default for 3D and realistic) | the lines in quotes in the clip prompt, each tied to its speaker by [ImageN]; Seedance makes voice and lip-sync | the series feel; 3D, realistic | wrong speaker; voices drift between clips; the model adds its own subtitles |
| **B. Narrator** | an ElevenLabs voiceover (the hero's diary voice "I used to…" or a third-person storyteller) over clips with ambience and action sound only | 2D, kawaii, storybook, stop-motion; exact wording; cheap localization | less "series" feel; VO must match the cuts |
| **C. Mixed** | dialogue in the key scenes (witness lines, the turn, the button), the hero's inner voice over the montage (the pain chain fast-cut, the "Day 14" payoff) | longer films; montage-heavy stories; confessions | two voice sources must sound like the same person: the inner voice uses the hero's voice anchor |
**Writing the lines:**
- **Short and in character.** One line per 3 to 5 s of screen; most lines under 8 words. A witness line is a reaction ("Are we… boring you?"), not an explanation.
- **Subtext over exposition.** "He's just excited" tells us she's embarrassed; "My dog is untrained and it's ruining my life" tells us nothing we feel.
- **The objection can be a line.** "I can't afford a trainer", "I've watched a hundred YouTube videos": the messenger's answer is the app's value.
- **The app is named once** by the messenger (or appears through the plot), with the one feature by its real Brand Kit name. The hero's button line can name it again or just show the phone.
- **Word budget:** a drama breathes. Plan about 1.5 to 2 spoken words per second across the film (75 s ≈ 110 to 150 words), up to 2.5 inside a dialogue scene; the narrator at 2.0 to 2.5. Count them per clip.
- **Spoken numbers and names** as pronounced; check the app name in every result.
- **Language:** write natively for the market, not translated word for word. In mode A another language means new clips (or mode B for that market); in mode B only the VO changes, the clips stay (`lyra-audience-variations` for the rest).
**Voice consistency across clips (mode A).** Same voice anchor, same model, one speaker per line. If a voice drifts, offer: regenerate the clip; or **voice lock**: record each character's lines as a voiceover node (the ElevenLabs model `list_node_configs` lists first; one saved voice per character), then give Seedance 2.5 that audio as reference for lip-sync (up to 30 s of audio per clip). In a two-speaker clip, [Audio1] is one character's lines and [Audio2] the other's, each tied to its speaker in the prompt; if the wrong mouth moves, one clip per speaker. Exact words and the same voices in every clip, a little less natural acting (base Reference C).
**Music.** One score for the whole film (`elevenlabs/music`, instrumental, length = film + ~5 s) with an arc written in the brief: light comic tension in the pain chain → it drops out or goes soft at rock bottom → a warm lift at the turn → bright and resolved at the payoff → a short button for the end card. Or two tracks (before / after) crossfaded at the time jump. Under dialogue about 0.1 to 0.2 track volume; up to ~0.3 under a narrator; louder in the title cards only if the music track is split there (otherwise keep one level). The times in the music brief are approximate; align by trimming in the editor. Clip prompts: "Sound: dialogue and natural ambience only, no music, no score."
**Captions.** Asked first in the approval message (base rule). If yes: all speech, added in the Video Editor, by the base rule (`lyra-video-editor` → Captions): size 80, at 75% of the height (y = 1440 on 1080×1920), never over a face, high-contrast, one place. Series look: white with a dark outline or shadow; karaoke style (the editor's active-word highlight in a brand color, used in Lyra's own story templates) also works well in this format. The user checks the words and the app name.
**Chapter markers and title cards.** Clock times ("7:15"), days ("Day 14"), places ("Monday"): text added in the Video Editor over the first second of each scene; a full title card is a plain black or brand-color 9:16 image (uploaded, or a plain Nano Banana Pro image without text) held 1 to 1.5 s with the text added in the editor. Text and captions are added in the editor's interface: in the final report, list for the user exactly which captions, chapter markers and title cards to add and where.
---
## Openings (use `lyra-video-hooks`)
The cold open decides whether anyone sees the story; most viewers decide in the first 3 s. Read `lyra-video-hooks` and write 3 to 5 opening options in the concept, one recommended:
- **Peak disaster, mid-action** (default): the worst or funniest moment of the pain chain, already happening ("soaked in the bathroom, the dog bolting").
- **Conflict line:** a witness says the sharpest line at frame 1 ("You have to do something about that dog.").
- **Twist first line** (confession, realistic): "It took me getting divorced at 35 to realize…".
- **Fast chaos montage:** 4 quick shots of the pain chain in the first 6 s, then the story starts.
- **Flash-forward:** a glimpse of the payoff, then "3 weeks earlier…" (good when the payoff is visual and surprising).
- **Fourth-wall aside:** the hero looks at us: "This is me. Day one of being a dog mom." Then chaos.
- **Chapter clock on chaos:** "7:15" over a crash sound and the aftermath.
For a test, keep one body and build N openings (hook skill, mode A): only the first 3 to 6 s change (Praktika runs one opener on several bodies; the reverse also works). Caption on frame 1, 2 to 6 words. Hook code in the final's name.
## Ad copy around the video
Write it into the script node as "Ad copy (for Ads Manager)", for the user or media buyer to paste:
- **Primary text:** line 1 continues the story's hook in a few words ("She almost gave him back."), then the app name and 3 to 5 real features as short lines (the Woofz pattern), the offer, the CTA. Only Brand Kit facts.
- **Headline:** the promise or the offer in 5 to 8 words.
- **One per language**, written natively.
---
## Series option
On request, or when the story is long and the user wants retargeting:
- **2 to 3 episodes, 60 to 90 s each,** one workflow with a shared **Cast** section (character sheets, location keyframes) and one Section per episode, each with its own clips and Video Editor.
- **Each episode is a complete ad:** it opens on conflict, has its own mini arc, names the app and ends with the end card (cliffhangers alone don't make people come back). Episode 1 includes the turn and stops before the payoff ("…tomorrow I'll find out if it works."); episode 2 opens with a 2 to 3 s "previously" flash and pays off; episode 3 can be another pain or the comeback.
- **Episode markers** in post: "Episode 1", "Part 2" on frame 1 or the end card.
- **Media plan line for the report:** run episode 1 to cold audiences; retarget people who watched 50%+ of it with episode 2 (a video-viewer audience or ad sequencing, where the campaign type allows it; app campaigns can limit this); exclude installers. The user's media buyer decides; this is a suggestion.
- Naming adds the episode: `…-E1`, `…-E2`.
---
## Best way to build it
The user's explicit choices override any row. Models and prices: base Reference A.
| If the drama is | Best approach (graph) | Models |
|---|---|---|
| **60 to 90 s, 3D or realistic, dialogue** (default) | Story script (text) → character sheets (count 2, user picks) → location keyframes from the sheets → phone image (hero + logo or screenshot) → **pilot clip** (the cold open scene) → after the user's OK, the remaining **3 to 4 clips of 15 to 30 s**, grouped by place and cast, each with "cut to" shots inside → music → Video Editors (the film, the 59 s cut, the 30 s cut, the teaser) | nano-banana-pro · seedance-2.5 · elevenlabs/music |
| 2 min | as default, 5 to 6 clips | same |
| 2D anime, storybook, kawaii | as default, but clips of 8 to 15 s on Seedance 2.0 (6 to 9 clips for 75 s); narrator (mode B) by default; multi-shot clips take the character sheets and keyframes as references (as Lyra's Bunny and Kitten story templates do); a single-shot clip that must match its keyframe exactly takes it as first frame instead; never frames and references in one node; frame links are made right after the keyframe has a result (base Step 4) | nano-banana-pro · seedance-2.0 · elevenlabs VO + music |
| Stop-motion, knitted, clay, felt | keyframe per scene; one video model for the whole film: Seedance 2.0 with the keyframe as first frame (as Lyra's Knitted Doll template) when the film is narrated, Seedance 2.5 refs when characters speak; "subtle stop-motion feel" in every clip | nano-banana-pro · seedance-2.0 or 2.5 |
| Realistic confession | one speaker sheet (face close-up + full body) → the set keyframe → 2 to 3 clips of the talk with listener cutaways → past flashes as short clips → mode C | nano-banana-pro · seedance-2.5 |
| Exact words or fixed voices (mode A, voice lock) | each character's lines as ElevenLabs VO → audio reference in the Seedance 2.5 clip | elevenlabs (v4 / v3 as listed) · seedance-2.5 |
| Series of 2 to 3 episodes | one workflow: shared Cast section, a Section and a Video Editor per episode | as default |
| A drama system (many heroes for one app) | build the first film; each new hero, pain chain or language as a Lyra variation of it (`lyra-audience-variations`, `lyra-ad-concept-multiplier`) | as default |
| Several openings on one film | the film here, openings from `lyra-video-hooks` mode A, each its own short clip cut onto the shared body | as the hooks skill |
| Another market | mode B: new VO only; mode A: new clips with lines written in that language (or voice lock); `lyra-audience-variations` for the rest | as default |
| Tight budget or story test | motion comic (keyframes + slow camera moves) or drafts on Seedance 2.0 Fast at 720p; rerun the winning story on the full models | seedance-2.0-fast · seedance-2.0 |
| A competitor's drama to adapt | `lyra-copy-competitor-ad` analysis (beats, timing, mechanism) → this skill's build with our hero, pain chain and app | as default |
**Clip plan.** A clip holds the scenes that share a place and a cast (Seedance 2.5 up to 30 s, Seedance 2.0 up to 15 s), with "cut to" shots inside; a new place usually means a new clip. The cold open is its own clip (the pilot, and the piece replaced in hook tests). The turn gets its own clip (the most important scene for the ad). Write the end state of every clip; the next clip starts from it. Clips are trimmed in the Video Editor, never stretched.
**Pilot clip gate.** Before spending on 4 to 8 clips, run one: the cold open with the hero and a witness. The user checks style, faces, voices, lip-sync and the pace. Fix the prompt, the references or the model on the pilot; only then run the rest. Say this in the plan; it saves the most credits in this format.
**Video Editor.** One `video_composer` per film and per cutdown: clips in playback order → title cards and chapter markers on the layer above → the phone or logo insert if needed → the end card → music on its own track (no clip with dialogue carries music), the clips' own sound kept for dialogue and ambience, the VO track in mode B or C. Captions for all speech, if the user said yes. Check the order and set `startMs` after the clips have results.
**Layout.** Section "Story" (story script, cast cards, ad copy) → Section "Cast" (character sheets, uploads: logo, screenshots) → Section "Keyframes" (locations, phone image) → Section per act or episode ("Act 1: the bad day", "Act 2: the turn", "Act 3: the payoff") with its clips → Section "Audio" → Section "Final" (Video Editors: film and cutdowns). Labels: "Cast: Mia", "Place: kitchen night", "Clip 2: office disasters (24 s)", "Final: D1 75 s", "Cut: D1 59 s", "Cut: D1 30 s".
## Run options for short drama
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits are read from the nodes, never guessed. This is the most expensive format in the set: in the plan, say so and give the clip count × seconds per clip; in Run options, read every node's price and show each option's credits plus the whole-film total, before anything runs.
| Option | Runs | Results | Credits | Time |
|---|---|---|---|---|
| **A1. Cast (recommended first)** | character sheets (count 2) | the faces and the look; the user selects one sheet per character in Lyra | {x} | ~1 min |
| **A2. Keyframes** | location keyframes + phone images (from the selected sheets) | every scene's look | {x} | ~1 to 2 min |
| **B. Pilot clip** | the cold open clip | style, faces, voices checked on one clip | {x} | ~3 min |
| **C. The rest of the film** | remaining clips + music (+ VO in modes B and C) | all pieces | {x} | ~5 to 10 min |
| **D. Final** | Video Editors (no credits) | the film and the cutdowns | 0 | ~1 min |
Whole film: {x} credits · balance {X}. Run A1, then A2 after the user's selection (references pin to the selected result), then B, then C.
---
## Prompt rules (short drama)
| Node | Write | Avoid |
|---|---|---|
| Story script (text node) | logline · style anchor · cast cards with voice anchors · the beat sheet with times, chapter markers, places, witnesses, the brand thread · every line per clip with its speaker and word count · title cards · captions marked for post · music arc · end card · cutdowns · ad copy | ad copy inside the film's lines; claims not in the Brand Kit; a single block of prose without timings |
| Character sheet | style anchor → the card word for word → full body, front three-quarter, neutral pose, plain soft background → "single character, one image, no text" | studio or artist names; text; several poses in one image (unless a turnaround is wanted) |
| Location keyframe | "Use the exact characters and style from the reference images" → the scene: who, where, doing what, the emotion at the start of the scene → the set with 2 to 3 story details (the puddle, the coffee stain) → light and time of day → framing for 9:16 → "single illustration, one scene, no comic panels, no speech bubbles, no text" (for realistic: "single photograph, one scene, no text") | re-describing the faces (the reference holds them); comic panels; captions |
| Phone image | the hero holding the phone toward the camera in the style, the screen showing the logo or screenshot from the reference "exactly as in the reference, every letter" | an invented UI; a placeholder app name |
| Clip (Seedance 2.5, references) | style anchor first → roles: "[Image1] is Mia… [Image2] is the kitchen at night" → the scene and its shots with "cut to" → the action before each line → each line in quotes after its speaker, the listener silent → acting through actions (she freezes, he blinks slowly) → camera per shot → "Sound: dialogue and natural ambience only (the scene's own sounds: a door, steps, cups); no music, no background music, no soundtrack, no score" → the end state → "No subtitles, no captions, no on-screen text" → short Avoid line | stage directions inside quotes; more than one line per 3 s; music in the clip; the full look re-described |
| Clip (Seedance 2.0, 2D) | style anchor → roles → one simple action per shot, expressive poses → slow camera moves → sound line (no speech in mode B) → end state → no text | complex choreography; long dialogue in flat 2D |
| Narrator VO | the exact words only, one continuous text, sized to the film minus ~1 s, the hero's voice or a storyteller | labels, brackets, "(sad)", scene names |
| Music brief | genre, tempo, instruments, the arc with times (comic tension 0 to 28 s → soft 28 to 33 s → warm lift 33 s → bright 44 s → resolve on the end card), instrumental only, length = film + 5 s | artist or film names; vocals |
**Pattern: clip with dialogue (Seedance 2.5, references, 3D animation).**
> Style: stylized 3D animated feature film look, soft rounded character design, big expressive eyes, warm global illumination, detailed lived-in sets. [Image1] is Mia: dark curly hair in a low ponytail, small gold hoops, sage-green overshirt, white tee. [Image2] is Dana, her boss: sharp grey bob, black blazer, red reading glasses. [Image3] is the glass meeting room at 10:30, morning light, a client presentation on the screen. Shot 1, medium shot: Mia is asleep upright at the table, her cheek sliding slowly down her hand. Dana stops mid-sentence, lowers her glasses and says flatly: "Are we… boring you?" Cut to: close-up, Mia jolts awake, a sticky note stuck to her cheek, eyes wide. She says: "No! No. I was… visualising." Cut to: Dana's slow blink, she says nothing. Dialogue and natural office ambience only, no music, no background music, no soundtrack, no score. Each line spoken by its speaker only, the listener silent. Ends on Mia peeling the sticky note off, mortified. No subtitles, no captions, no on-screen text. Avoid: photoreal faces, identity drift, outfit change, extra fingers, flicker.
(9 spoken words in a ~9 s clip: the 3 s cold open plus the first beat after it; this clip is also the pilot. When the brand thread is planned here, connect the messenger's phone image as [Image4] and add one line: "on the table, Jess's phone lies face-up showing the screen from [Image4]".)
**Pattern: location keyframe from the character sheets.**
> Use the exact characters, faces, outfits and style from the reference images. Stylized 3D animated feature film look, soft rounded character design, warm global illumination. New scene: a small kitchen at 23:55, Mia sits on the floor against the fridge, still in her overshirt, hair down, with a mug, the phone's light on her face, tired and teary; a sink of dishes, a half-eaten cereal bowl, her work badge on the counter. Cool blue night light from the window, a warm stove lamp. Vertical 9:16, Mia in the lower middle third. Single illustration, one scene, no comic panels, no speech bubbles, no text.
**Pattern: realistic sitcom clip (Seedance 2.5, references).**
> Naturalistic real-life scene, handheld camera at eye level, available daylight, natural skin texture, unpolished. [Image1] is Rafael: early 30s, short dark hair, light stubble, rust-colored t-shirt, a backpack. [Image2] is the barista: late 40s, grey beard, rolled-up sleeves, a canvas apron. [Image3] is a small café abroad, a counter with pastries, a queue behind Rafael, morning light from the street. Rafael tries to order, the barista answers fast in the local language, Rafael freezes and points at a pastry. Cut to: the woman behind him in the queue, hiding a smile. Cut to: the barista slides the coffee over and says kindly, slowly: "Next time, you order in full sentences, okay?" Rafael laughs at himself: "Deal." Dialogue and café ambience only, cups and street noise, no music, no background music, no soundtrack, no score. Each line spoken by its speaker only. Ends on Rafael stepping outside and taking out his phone. No subtitles, no captions, no on-screen text. Avoid: identity drift, plastic skin, warped hands, people turning to camera.
(The cold open and first pain beat of a fictional language app's comeback story; in a real build the app, the lines and the market come from the user's Brand Kit.)
**Drama prompt checklist:** style anchor · who is who ([ImageN]) · where and when (time marker) · one action per shot · the line and its speaker · the emotion at this beat · camera per shot · light (pain chain cooler, payoff warmer) · sound line · end state · no text.
## De-slop for short drama
Base Reference H, plus what breaks long stories:
- **Style drift:** 3D turns photoreal in close-ups, 2D gains 3D shading, the knitted world turns plastic, realistic skin turns waxy. Prevent: the style anchor first in every prompt, the sheets as references, one model per film; "Avoid: photoreal faces" in stylized clips.
- **Character drift between clips:** hair, glasses, outfit color, the dog's breed change. Prevent: signature outfits, cards word for word, 2 to 4 references per clip, cuts on chapter cards.
- **Generated text:** the model adds subtitles to dialogue scenes, writes on screens, signs and phones. Prevent: "No subtitles, no captions, no on-screen text" in every clip; real logo only through the phone image.
- **Dialogue slop:** the wrong character speaks, both talk, mouth moves with no words, voice too old or too young for the face, the app name garbled, silence under AI voices.
- **Story slop:** the viewer can't tell who the hero is in 3 s; scenes that don't escalate; the app arriving in the last third, or as a forced insert; an instant magic fix; a payoff that doesn't mirror the pain; a "happy montage" with no witness.
- **Acting slop:** constant smiling, floaty gestures, everyone overacting at once. Big acting is fine, but one clear emotion per beat; in realistic drama, heightened but never parody.
- **Edit slop:** dead air between lines, cuts that jump the axis, the music fighting the dialogue, the end card held 10+ s, chapter markers outside the safe zone.
---
## Truth and safety
- **The drama is fiction.** Characters are invented, the story is a creative scene, never presented as a real customer's story. A witness or messenger line is dialogue, not a review. Real reviews and ratings appear only as text on the end card, attributed.
- **Dramatizations stay dramatizations.** In the US, people presented as actual customers must be real or clearly disclosed as not (FTC Endorsement Guides; the FTC rule on fake and AI reviews bans AI testimonials that misrepresent the speaker). A confession or a first-person "I used this app" scene with an AI person gets a visible "Dramatization" / "AI-generated story" note.
- **AI labels.** Meta labels and detects AI content (C2PA); TikTok requires the "AI-generated content" box on fully AI ads. Under the EU AI Act (Article 50, applying from 2 Aug 2026 per legal analyses at the time of writing) realistic synthetic people are expected to carry a visible label at first exposure, and the platform's label alone may not cover the advertiser; clearly stylized animation is less likely to count, but keep the platform label on. Tell the user once in the final report. Not legal advice; they check current rules.
- **Only Brand Kit claims.** The feature, the program names, the time to result ("Day 14" only if the Brand Kit supports two weeks), the offer, prices. No health, money, weight, pet behaviour or child results the app can't stand behind; no body before / after.
- **No real people, celebrities, creators, studio characters or lookalikes;** no studio or franchise names in prompts; no cloned voices.
- **Story formats that imitate platforms** (a forum post, a chat, comments): never copy a real platform's interface, logo or name, and never fake user comments as social proof. Write a neutral, clearly fictional post or chat, or use the film instead.
- **Brand-safe drama** (base Reference B): no violence, abuse, cheating, humiliation of a group, profanity, politics or competitor digs; minors only as side characters in family scenes, never in distress for the plot; pets are never hurt; mental health without crisis, self-harm or cure claims; the Brand Kit's forbidden claims enforced absolutely.
---
## Deliverable and naming
1. A "Story script" text node: logline, style anchor, cast cards, beat sheet, lines per clip, title cards, captions marked for post, music arc, cutdowns, ad copy.
2. Character sheets, location keyframes, the phone image, clips, music (and VO).
3. The finished film in its Video Editor plus the cutdowns (59 s, 30 s, teaser), and one Video Editor per episode in a series.
Name every final with a code the media buyer can paste into Ads Manager: `B{batch}-A:{angle}-F:Drama-{style}-{length}-C{concept}H{hook}[-E{episode}]`, e.g. `B3-A:SleepWrecksWeek-F:Drama-3D-75s-C1H2`, `B3-A:SleepWrecksWeek-F:Drama-3D-59cut-C1H2`, `…-Real-…`, `…-E2`. Node label: "Final: D1 · 3D · 75 s · H2".
---
## Common mistakes (short drama)
| Mistake | Prevention |
|---|---|
| Different background music inside the clips, fighting the score under the dialogue | Every clip: dialogue and scene sounds only, "no music, no background music, no soundtrack, no score"; the score only in the Video Editor; rerun a clip that still has music (base Reference C) |
| One concept offered when the user asked for ideas | Three different concepts (structure, style, integration), one recommended |
| Story without a pain map: a generic sad person, a generic happy person | Pain map → hero → pain chain from the Brand Kit; the Category guide |
| Opens on an establishing shot, a sunrise or a logo | Cold open at the peak of a disaster; `lyra-video-hooks` |
| Pain scenes that repeat instead of escalating | Each scene costs more: time → money → face → a relationship |
| The app only in the last third, so most viewers never see it | Brand thread early; the turn at 35 to 55% (up to ~60% in 2 min) |
| The app as a forced insert | The app moves the plot (L2 or L3) |
| The app fixes everything instantly | An honest time card from the Brand Kit |
| Payoff in new places with new people | Mirror scenes, the witness reversal |
| A studio or franchise name in prompts, a known character's look | Describe the look; original characters only |
| Style or faces drift across clips | Style anchor first, character sheets as references, signature outfits, one model |
| The whole cast connected to every clip | 2 to 4 purposeful references per clip |
| Subtitles or text generated in the clip | "No subtitles, no captions, no on-screen text"; captions in the editor |
| Lines too long, rushed voices, the wrong speaker | One line per 3 to 5 s, speaker by [ImageN], listener silent; voice lock if needed |
| Realistic AI people presented as real customers | Fiction frame; "Dramatization" / AI note; AI label |
| Invented app UI on the phone | Logo screen or real screenshot through the phone image; else screen away |
| All clips run at once, the style fails on clip 5 | Pilot clip gate |
| One score with vocals or a track that ends early | Instrumental, film + 5 s, an arc, trimmed with a fade |
| Only a 75 s+ version | The 59 s cut for all Meta placements, plus 30 s and a teaser |
| End card held 10+ s | 2 to 4 s |
| One drama and done | A drama system: new heroes, pains and languages as variations |
| Melodrama tropes that hurt the brand | App-safe versions; brand safety |
| Forgetting the AI label | One line in the final report |
## Quality gates (short drama)
- **Stage 0 (story, Claude checks before sending):** three concepts offered (unless the story was given)? The logline has a hero, a pain, a turn, a payoff? The hero is likeable and from the audience? Conflict in the first 3 s? Every pain scene escalates and has a witness? A brand thread early, the turn at 35 to 55% (up to ~60% in 2 min), through a messenger or the plot, with one real feature? An honest time jump? The payoff mirrors the pain, with a witness reversal? Lines counted per clip? No claims outside the Brand Kit? No studio names? Cutdowns and ad copy planned?
- **Stage 1 (cast and keyframes):** each character looks the same in every keyframe? The style is the same everywhere? The emotion at the start of each scene reads at a glance? The phone shows the logo or screenshot exactly, or is turned away? No text in images?
- **Stage 2 (pilot, then all clips):** faces, outfits and style hold within and across clips? The right person speaks, the lip-sync fits, the voices fit the faces and stay the same? Acting reads muted? No generated subtitles or text? Each clip ends on its planned end state?
- **Stage 3 (final), app ad check:** does a viewer who leaves at 10 s know the app and the promise? Does a muted viewer understand the story with captions? Is it clear what the app does for the hero, and is that what the store page and the first session give? Is the CTA an install or trial step with the real offer?
- **Stage 3 (final):** hook in 1.5 to 3 s? Beats in order, the turn at 35 to 55% (up to ~60% in 2 min)? Chapter markers inside the safe zone, captions (if the user said yes) size 80, at 75% of the height, not over a face? Music under the dialogue, the arc landing at the turn and the payoff? End card 2 to 4 s? 9:16, planned resolution (720p by default), the planned length? 59 s, 30 s and teaser cuts made? Dramatization note where needed? Named with its code? AI label reminder given?
## After the test
Read the drama by where people leave, not only by CTR:
- **Hook rate** (3 s plays ÷ impressions; above 30% good, under 20% weak, base Reference J), **hold rate** (ThruPlays ÷ 3 s plays; about 40 to 50%; a ThruPlay counts at 15 s, so for long ads also read the retention curve), plays at 25 / 50 / 75 / 100%, the share who reach the turn; on TikTok, 2 s and 6 s views and quartiles.
- Then installs per 1,000 impressions, cost per trial, trial to paid and day-7 retention. Dramas can bring fewer but better clicks; judge them by trials and payers, against your best UGC.
**Diagnose:** drop in the first 3 s → new cold opens (`lyra-video-hooks`); drop in the pain chain → shorter Act 1, the 59 s or 30 s cut; viewers reach the turn but don't install → the turn or the offer (a clearer feature line, stronger messenger proof, an objection answered); good results on the full film only → keep it, but put budget behind the cut that wins on cost per trial.
**Then build the system:** new openings on the winner; a new hero on the same story (`lyra-audience-variations`); a new pain chain or messenger on the same cast (`lyra-ad-concept-multiplier`, mode B); the same script in the other style (animated ↔ realistic); other languages; the next episode. The format fatigues fast, so plan 2 to 3 new variants for every winner.
lyra-static-image-generation79.2 KB
View saved version →
---
name: lyra-static-image-generation
description: "Base skill for images in Lyra. Builds static ads and images for mobile apps end to end (concept, layout, on-image text, realism, model choice, references, sizes, languages) with a clear concept and layout, photo-real realism on Nano Banana Pro, de-slop and error handling. Use for \"a static ad for my app\", \"an image ad / banner / creative\", \"4 statics to test\", \"a carousel\", \"a realistic photo of…\", \"a character / persona image\", \"a product or phone shot\", \"an illustration in our style\", or a layout or reference to produce. Holds the core image rules the smaller lyra image skills point to."
---
# lyra-static-image-generation
The main image skill for Lyra. It holds the core rules for every image: concept and layout, on-image text, realism, styles, models, references, consistency across a series, de-slop and error handling. Smaller image skills (resize and translation, store screenshots, competitor statics, audience swaps, and the image mini skills still to come) point here for these rules. Video skills use this skill's realism and image prompt craft for their keyframes, character images and phone shots; the role of those images in the video stays with the video skill.
Part 1 is shared by every Lyra skill (the same 8 steps as `lyra-video-ad-generation`, written for images). Part 2 is what's specific to static images. The Reference library at the end has the details (models, layout library, text, realism, styles, consistency, UI, errors, de-slop, Meta statics).
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**This is a way of thinking, not a script.** The rules are defaults and good practice; use judgment and say why in one line when you choose differently. Fixed: truth (no invented claims, reviews, numbers, UI or logos), the Brand Kit's facts, UI fidelity (the user's screenshots, exactly), Lyra's technical limits, and the user's explicit choices.
---
# Part 1. [SHARED] How every Lyra skill works
**Deliverable:** a Lyra workflow in which every planned node has been generated. The user opens the canvas and finds the results, the prompts that produced them, and a graph they can edit and rerun for the next app, angle, size or market.
A full creative always follows these steps, in order:
1. **Context.** Collect the app context and task inputs; make sure you have everything before proposing anything.
2. **Concept and plan.** A very short concept with its layout, plus a short plan of nodes, models and connections, based on "Best way to build it".
3. **Approval.** One message: concept, plan, open questions and the cost in credits; the user approves or corrects. Nothing is created before this; the yes also starts the run.
4. **Build.** Create the workflow and nodes with the chosen models, write every prompt into the node's prompt field, upload and connect the assets. Nothing runs yet.
5. **Pre-run check.** Right before every run, read the workflow back and restore anything lost (connections, settings); keep the user's own edits.
6. **Credits and run.** The cost is part of the plan; after the one yes, build and run everything without asking again.
7. **Run and report.** Run, report with the right links (workflow, video or image) and the real spend, offer the next step.
8. **Verify quality.** Check with the user against the quality gates.
## Whose instructions win
1. The user's explicit instructions in this chat.
2. This skill's best practices and defaults.
3. The brand kit: real app facts, claims, value proposition, features, audience, colors.
Best practices are defaults, not rules for the user. When a user's choice will likely hurt the result, follow it and say once in the plan what you'd do instead and why; don't argue twice. When a choice breaks a hard limit (transparent background on Nano Banana Pro, a ratio the model doesn't list), explain and offer the closest build that works.
## Step 1. Context
**App.** Every concept starts from the app. Generic ads come from missing product context, so never fill gaps from imagination.
1. Brand kit given in the chat → use it. Otherwise `list_brand_kits`: one kit → "Make this for {kit name}?"; several → ask which. The user may add or override details in chat.
2. No kit → ask once: send it here, or should I check / connect one of the kits already in your workspace? If the user prefers to type it: app name, what it does, who it's for, the pain it solves, 2–3 features the ad may show, approved claims and offer, forbidden claims, tone, brand colors (hex), assets (logo, app icon, **screenshots only**, product photos if the app has a physical product).
3. Keep the result as an **app card** for the whole session:
> App card: Calmly · 5-minute wind-down sessions for sleep · for students 18–25 · pain: can't switch off at night · may show: wind-down timer, sleep sounds · claims: none approved · offer: 7 days free · tone: calm, a bit ironic · colors: #1B1F3B navy, #8B7CF6 violet, #F4F1EA cream · assets: logo, icon, 3 screenshots · source: brand kit
**Ask only what only the user knows.** Lyra's own nodes never ask and fill every gap with reasonable assumptions (System Preamble). This skill asks once, in Step 1, only for what can't be assumed (the app, the screenshots and logo, the idea if they have one); for everything else it assumes, states the default in the plan and proceeds.
**Task.** Ask for the inputs in Part 2 → Inputs and defaults; state the defaults instead of asking. Ask for everything missing in one message; never re-ask what the user said. Call `list_workspaces` (credits) and `list_node_configs` (models, ratios, resolutions) now.
## Step 2. Concept and plan
Short: readable in under a minute.
**Concept:** per deliverable, the concept card (Part 2 → Concept and layout): hypothesis in one line, the visual idea, the layout map with every text in quotes, style and palette. N deliverables = N distinct ideas; more takes of one idea is `count` on a node, not more nodes.
**Plan:** name the matching row of Part 2 → Best way to build it in one line, then list the nodes:
| # | Node label | Node · model · key settings | Inputs (role) | Stage |
|---|---|---|---|---|
| 1 | Concept card (note for the user) | user text | — | — |
| 2 | Logo | upload image | — | 1 |
| 3 | Screenshot: timer | upload image | — | 1 |
| 4 | Persona: Mia | image · google/nano-banana-pro · 4:5 · 2K · count 2 | — | 1 |
| 5 | Ad C1: 2 am POV · 4:5 | image · google/nano-banana-pro · 4:5 · 2K | 4 (person), 3 (screen), 2 (logo) as references | 2 |
| 6 | Ad C2: proof shot · 4:5 | image · google/nano-banana-pro · 4:5 · 4K | 3, 2 as references | 2 |
| 7 | C1 · 9:16 + 1:1 | image resize · google/nano-banana-2 | 5 | 3 |
**One image by default.** A static ad is usually one Image Generation node that renders the whole ad: scene, person, phone with the real screen, headline and CTA. Add a separate source node only when: the same person appears in several images (carousel, a series, a later video) · the user wants to pick the face or the product shot first · the screenshot must sit in a phone shot that is checked on its own · a layout keeps failing and is easier in two passes (scene first, then text). Say in one line of the plan why you split or don't.
Stages: **1** = sources (uploads, persona, product or phone shot; fast) · **2** = the ad images · **3** = adaptations (other ratios, other languages, variants).
**Cost:** the plan's total in credits, from Reference A → Credit prices (count and duration included), next to the balance: "≈ 181 credits · balance 47 424".
## Step 3. Approval
**One message, one question.** Everything the user has to decide goes into one message: the concept, the plan with models and quality, any question you still have, and the **cost in credits** with the balance (Step 6). It ends with one question that covers all of it, e.g. "Do the 3 concepts, Nano Banana Pro 2K and ≈ 181 credits (of your 47 424) work for you? After your yes I build the workflow and run everything." Never a separate question about money or about running.
On corrections, show only what changed, with the new cost, and ask again. Don't create anything in Lyra before a clear yes. This yes also starts the run: after it, build and run everything without asking again (Step 6).
## Step 4. Build the workflow
1. `create_workflow` (or `use_template`, or the user's own workflow, or a variation of an existing one: Variations below), then `assign_brand_kit`.
2. Upload the assets the images need (`list_uploads` first, then `create_upload` + `attach_upload`, or `open_upload_widget`): logo, app icon, screenshots, product photos, style or layout references. Never generate a logo, icon, store badge or UI.
3. Write every prompt (Part 2 → Prompt rules). The concept card goes into a user text node (`create_user_text_node`) as a note for the user, connected to nothing. A user text node feeds its text into any node it is connected to, so keep this one unconnected (a Note on the canvas can't be connected at all, but the tools can't create one). The text doesn't keep the style or the person consistent: consistency comes only from images connected as references, plus the anchors written into every prompt.
4. Create every node from the plan with its prompt, its model, ratio and resolution from `list_node_configs`, and a label that says what it's for ("Ad C1: 2 am POV · 4:5", "Persona: Mia"), never "Image 1".
5. **Connect the whole graph now** (`connect_nodes`): uploads and persona → every image that uses them (reference) · the approved ad → resize and translation nodes. References connect before anything is generated, so "run all" works.
6. Lay out the canvas by `lyra-workflow-layout` (STEP notes, sections in reading order, colors, check), one section per stage: **Sources** (concept card, uploads) → **Persona / product** → **Ads** → **Sizes and languages**. An upload sits next to the node it feeds.
7. Check `is_valid` and `validation_error` on every node; fix with `update_node` using listed values.
## Variations, not new workflows
A new version of something that already lives in a workflow goes into a **variation of that workflow** (Lyra's **Create variation**), never into a new workflow, unless the user asks for a new one.
- **When:** a new version of a video (another story with the same characters, another angle, hook, person, setting, length or language, a remake of a failed take), more room for another round, splitting the work, or the user asks for several variations.
- **How:** `create_variation` (it copies the whole canvas: nodes, connections and results) with a clear title ("D2 · Dan's turn") → `switch_variation` to it (the tools and runs work on the main variation; Lyra also renames the workflow after it) → `delete_node` the nodes this version doesn't need → update the prompts and add the new nodes → connect → pre-run check → run. Nodes kept as they are keep their results and cost nothing (characters, places, the end card clip). The variation keeps the canvas layout: update the section titles and labels that name what changed (`lyra-workflow-layout`).
- Deleting inside a variation you just made for this version is part of the build and needs no extra ask. Never delete in the original variation or in one the user made.
- **Report:** the workflow link, the name of the variation with the new version, and that the original is untouched in its own variation (to show it again: `switch_variation`, which renames the workflow back).
- **Images:** new statics, sizes or languages can stay in the same variation as new nodes, one Section per set, unless the user asks for a separate workflow or the canvas gets crowded; then a variation, as for video.
- **Open canvas:** before editing an existing workflow through the tools, ask the user to close its tab or switch away (an open canvas can write its old state over the tool edits), and tell them when it's safe to open it again.
## Step 5. Pre-run check
Right before **every** `run_node` (the first run, each next stage, reruns, follow-ups). The canvas changes between build and run: the user edits it, and an edit on the canvas can drop or overwrite connections. A run with a missing input spends credits for nothing, so never trust what you built a few minutes ago.
1. `get_workflow` now, not from memory.
2. Compare it with the plan: every planned edge (source → target) is there · every node that takes images has them as planned (`image_inputs_usage`: references or frames; a frame points to an existing result) · every node `is_valid`, no `validation_error` · no empty prompt · settings as planned (model, ratio, duration, resolution, count).
3. Lost or changed by accident → restore it (`connect_nodes`, `update_node`) and say it in one line ("the link Character → Clip 1 was gone, reconnected"). Changed by the user on purpose (their prompt, model, a node they added) → keep it and use the workflow as it is now; never overwrite their edits. Not sure which → ask before running.
4. Inputs ready: a node runs only when every node it takes from has a result. Never run a node with a missing input.
After the build, tell the user once that the workflow is built and running and that they can edit any prompt on the canvas and rerun.
## Step 6. Credits and run
**Where the prices are.** `get_workflow` returns `credits` on every node: the estimated credits of one run of it (null = free: uploads, Video Editor, notes, user text; a Section shows the sum of its nodes; null on a paid node means a setting is missing, e.g. no resolution on Nano Banana 2: set it). Before the build, estimate with Reference A → Credit prices; after the build, read the real numbers off the nodes.
1. **In the plan (Steps 2–3):** the estimated total and the balance (`list_workspaces`), inside the one approval message.
2. **After the build, before running:** add up `credits` of every node that will run. Within ~15% of the approved estimate and within the balance → run everything, stage by stage (sources → ads → sizes and languages, Step 7), with no question. More than ~15% over, or over the balance → one short message: the new total, why, and a cheaper option (fewer concepts, lower count, 2K instead of 4K, Nano Banana 2); run after the answer.
3. **Reruns and follow-ups:** give the rerun's credits in the same message as the change ("Changed the headline; rerunning Ad C1 and its 9:16, 46 credits") and run, unless the user asked to check first.
4. **After the run:** the real spend (balance before − after) and the new balance.
5. A source image with count 2 (a character, a persona) feeds the next stage with its selected result; say in the report which one went on and that the user can switch (Step 7).
6. The smaller skills' **Run options** sections give the run order and what each stage holds: run all of it in that order, without offering the options. A staged run (the look first, then the rest) only when the user asks for it, or when the plan is expensive and the look should be approved first: then say so in the approval message, with each stage's credits, and run the next stage on the user's yes to the look.
7. No `credits` on the nodes at all (the field is gone): estimate with Reference A, say it's an estimate, and keep the same one-question flow.
## Step 7. Run and report
1. `run_node` on every node whose inputs are ready stage by stage: sources → ads → sizes and languages. Pre-run check (Step 5) before each stage. Keep each `run_uuid` and `variation_uuid`; call `get_run_results`; while `in_progress`, call it again. **Never call run_node on a running node** (second paid run).
2. **Picking a result.** A node with several results: when the user names one ("take the second", "the first one"), set it yourself on every node that uses it; don't send the user to tick it in Lyra. On a node with `image_inputs_usage` (video nodes): `update_node` with its whole `image_inputs_usage` from `get_workflow` and one field changed: references → `reference_result_image_uuids: [picked uuid]` (or the other results in `exclude_reference_result_image_uuids`); frames → `first_frame` / `last_frame` = `{"node_uuid": source node, "image_result_uuid": picked uuid}`. The results' uuids and their order (first, second…) come from `get_run_results` of the source node's run. Then `get_workflow` to check it held, and rerun what comes after it (pre-run check first). Only when the node has no such setting or the tool refuses: ask the user to tick it in Lyra and say why. Without a pick, the next stage uses Lyra's selected result; say which one went on.
3. Run a stage only after its inputs have results.
**Links in every report.** Never only file links. Two kinds of link, nothing else:
- **Workflow:** `https://lyra.splitmetrics.com/workflows/{workflow_uuid}` (opens for anyone signed in to Lyra with access to the workspace; results in a variation: name the variation to open).
- **Result:** the `url` from `get_run_results`, exactly as returned.
- one video → the video link + the workflow link
- several videos → the workflow link only
- one image → the image link + the workflow link
- several images → the workflow link only
Report:
> Calmly · statics · 3 concepts: done. Workflow: https://lyra.splitmetrics.com/workflows/{uuid} (3 ads, 9:16 and 1:1 each). Spent {x} credits · balance {X}. Open it to edit any prompt and rerun.
- Name failed nodes: label, what it was asked to do, why if known, the fix you suggest.
- When every node has a result, offer 2–3 next steps (variants of the winner, other sizes, other languages, an animated version).
- After the final images, run `lyra-result-check` straight away, without asking (free): it opens every image in a browser, checks faces, hands, text and logo, and reports the problems with pictures and fixes. Never describe or grade a result you haven't seen; without a browser send the stage checklist (Part 2 → Quality gates) and ask what works and what doesn't. Refer to nodes by label, never by uuid.
## Step 8. Verify output quality
Check final assets, not only job status: completeness (every concept, ratio, language) · message (one promise, hook, claims, offer, CTA match the brief) · text (every letter, every number, hierarchy, nothing extra) · visuals (realism or the chosen style, hands, faces, logo and UI exact) · layout (reads at phone size, safe zones, one focal point) · delivery (ratio, resolution, naming) · variations (intended difference visible) · reusability (prompts editable). Use Part 2 → Quality gates. Suggest fixes only for identified defects, within authorized scope and cost.
## Follow-ups
- One change ("make her older", "bigger headline", "warmer light"): `update_node` on that node, show the new prompt, pre-run check, rerun it and the nodes that depend on it (the rerun's credits in the same message, Step 6).
- A new angle, persona, size or language: hand over to the matching skill.
- Never delete or overwrite results the user may want: a new version goes into a variation (Variations above). `delete_node` only inside a variation you just made for this version, or when the user asks.
## Runtime failures
See Reference I. In short: validation_error → fix with listed values · run failed → name it, one retry with a changed prompt or model and its credits · in_progress → poll again · not enough credits → stop, show the balance and what's missing, offer cheaper (Step 6) · model refused content → tell the user, don't rephrase around it · file without public link → ask for a link or upload in Lyra.
## Base prompt rules
You write every prompt, and each lives in its node's prompt field, where the user reads, edits and reruns it. Write for the model and for the person.
- Self-contained: no "same as above", no references to the chat.
- Concrete and renderable: things the model can show, not marketing concepts.
- The user's own words for the subject and anything they specified stay as given.
- Settings (ratio, resolution, count) go in node settings, not in the prose.
- English, unless text must appear in another language. Exact on-image text in quotes.
- No placeholders, alternatives or "if" branches in a final prompt.
## Common mistakes (every skill)
| Mistake | Prevention |
|---|---|
| Builds or runs before concept and plan are approved | Steps 1–3 first, always |
| Asks about the price or the run as a separate question | Cost goes into the one approval message; the yes starts the run (Steps 3, 6) |
| run_node on a running node | Poll get_run_results |
| Plan without a cost, or a run without reading the nodes' credits | Reference A → Credit prices in the plan; node `credits` before the run |
| Runs with lost connections, or over the user's canvas edits | Step 5 pre-run check before every run |
| Sends the user to tick a result in Lyra | Step 7: set the picked result yourself |
| A new workflow for a new version of the same ad | Create variation of the same workflow, delete what this version doesn't need (Variations) |
| Only file links, or no workflow link | Step 7 links |
| Invents app features, UI, numbers or reviews | Only the app card; without screenshots keep the screen out of view |
| Swaps the user's explicit choice for a default | Instruction order; mention the trade-off once |
| Values the model doesn't list | Copy from list_node_configs |
| Nodes for takes of one idea, or count for different ideas | Ideas → nodes; takes → count |
| Prompts that point back to the chat | Self-contained prompts |
| Reruns an unchanged prompt as a fix | Change prompt, reference or model; say what changed |
| Describes or grades results it can't see | Ask the user with the stage checklist |
---
# Part 2. Static image generation: what's specific
## Description
Creates static ads and images for mobile app paid ads in Lyra, SplitMetrics' node-based creative canvas, leaving a generated, reusable workflow on the canvas.
Use when the user asks for "a static ad", "an image ad / banner", "statics to test", "a carousel", "a realistic photo of…", "a persona / character image", "a product or phone shot", "an illustration in our style", or hands over a layout, a sketch or a reference image.
Works from a Lyra brand kit or app details in chat, app screenshots, logo and icon, product photos, a reference static (through `lyra-copy-competitor-static`), or an existing workflow.
Not for: other sizes or languages of a finished image (`lyra-adapt-image`, rules from Reference H here) · App Store / Google Play screenshot sets and store-style end cards (`lyra-ui-motion-video`) · copying a competitor's static (`lyra-copy-competitor-static`, which builds on this skill) · the same image for another audience (`lyra-audience-variations`) · video (`lyra-video-ad-generation`).
## Quality bar
Reads in half a second at phone size (one focal point, one promise, a short headline), stops the scroll because it looks native and specific, shows only real app features and the user's real screens, every letter and number exactly right, one CTA, on brand, and no AI look: when the brief asks for a photo, it looks **taken by a camera, not generated**.
## Inputs and defaults
**Required (ask if missing):** the app (brand kit or app card) · the idea or the angle, if the user has one · app screenshots, if the ad shows the app · the logo file, if the ad shows the logo.
**Defaults (don't ask; state them in the plan):** Meta (Facebook / Instagram) · **4:5** master for Feed (9:16 when the user says Stories / Reels; 1:1 when asked) · other ratios as a follow-up, **recomposed, not cropped** · English · **photo-real** style unless the brand or the brief says otherwise · **Nano Banana Pro** for every final (`google/nano-banana-pro`) · **2K** (4K when the image carries small text, a UI screen to read, or a close-up face) · count 1 (2 for the hero or the persona when the user wants a choice) · one CTA · headline 2–8 words · text on ≤ ~20% of the canvas.
**In the plan, always say which model and resolution you recommend and why, and ask whether the user prefers another.**
**Run:** everything after the one yes, in stage order (Step 6).
## Image types: what we make
| Type | What it is | Default build |
|---|---|---|
| **Static ad** (the main job) | one finished ad: visual + headline + CTA (+ logo, UI) | one Pro node, the whole layout in the prompt, references connected |
| **Carousel** | 2–10 cards that read as one story, card 1 carries the hook | one Pro node per card, the same anchors in every prompt; persona / style reference shared |
| **Persona / character** | a person (or mascot) reused across ads, a carousel or a later video | Pro, front-facing or three-quarter, the pain place, count 2; Character Generation rules (Reference E) |
| **Product or phone shot** | the user's screenshot on a phone in a hand or on a backdrop; the app icon; a physical product from the user's photos | Pro with the screenshot / photo connected, fidelity line (Reference G) |
| **Scene / background plate** | a place or backdrop with a clean zone, no text, for the user's designer or for other images | Pro, "clean empty area for text in the upper third" |
| **Keyframe for video** | the first (or last) frame of a clip | built here for realism, at the video's ratio; its role follows the video skill |
| **Illustration / mascot / 3D** | a non-photo style: vector, hand-drawn, watercolor, kawaii, clay 3D | Pro (style described fully) or the style model of Reference A; the brand's own mascot only |
| **Typographic / text card** | type is the hero: a question, a statement, a list, a quote from a real review | Pro, every line in quotes with its style; Ideogram 3.0 as an alternative to test |
| **Cutout / sticker / icon-like element** | an object on a transparent background for a designer | GPT Image 2 with `background: transparent` (only 1:1, 3:2, 2:3) |
| **Edit of an existing image** | change one element, swap the person, change the light, remove a thing | Pro with the image connected, "change only…" (Reference F, edit pattern) |
## Concept and layout
A static has no time: the concept and the layout must be clear in one look. Every concept is written as a **concept card** before any prompt:
> **C1 · Pain POV · 4:5.** We believe students who can't switch off at night will start a trial because a relatable 2 am phone-photo shows the wind-down timer working. **Visual:** Mia, 21, lying in bed at 2 am, phone light on her tired face, holding the phone toward us with the real timer screen. **Layout (top → bottom):** top 22%: headline "2 am. Brain won't stop." white bold sans, left-aligned · middle 60%: Mia and the phone, screen large and front-facing · bottom 18%: CTA button "Try it tonight" in #8B7CF6, logo bottom-right small. **Style:** UGC phone photo, lamp light, deep focus. **Palette:** navy night, warm lamp, violet CTA. **Text total:** 7 words.
**What makes a static concept work:**
- **One promise, one focal point.** One pain or one benefit, one hero (a face, a phone, a result, a big line). A second idea is a second ad.
- **The hook is the picture plus the headline.** They say one idea together (the tired face + "2 am. Brain won't stop."). A picture and a headline that say different things fight; pick one.
- **Specific beats generic.** An exact moment, an exact object, the audience's own words. Stock-photo lifestyle reads as an ad and gets scrolled.
- **Native beats designed.** For cold traffic, a believable phone photo, an in-app proof shot or an apparent post usually beats a glossy billboard layout. Polished brand design is for premium or warm audiences.
- **Show the app only from real screens.** One key screen, large and readable, or no screen at all.
- **CTA names the action** ("Try it tonight", "Start free"), one per ad.
- **Hypothesis is a whole concept**, not one cosmetic change (Lyra's Creative Brief rule): "before/after + 7-day trial addresses doubt", not "a green button". Every concept connects to a testable idea and says **why** it should work: the user is trying to learn what works and why (System Preamble).
**Layout map rules** (written for every concept, copied into the prompt):
- Zones from top to bottom (and left to right), each with what's in it, roughly what share of the frame it takes, and its exact text.
- One reading order: the eye goes 1 → 2 → 3 (usually visual or headline → proof → CTA).
- Text in clean zones with enough contrast (sky, wall, a solid band, a darkened area), never over faces, hands or the screen.
- Safe zones: 9:16 keeps the top ~14% and bottom ~20% free of key content (platform UI); 4:5 and 1:1 keep ~5% margins. The hero sits in the central 65%.
- Logo small (about 8–12% of the height), in a corner, never the hero. Most native statics need no logo at all; the ad account shows the brand.
The **layout library** (Reference B) has the formats that work for apps, each with zones and a build note. The concept picks one and adapts it.
## On-image text
Unlike video, a static carries its text in the image, and Nano Banana Pro renders text well when it is told exactly.
- Every text block in **quotes**, with its zone, size feel (huge / large / small), weight, case, color (hex or name) and alignment: `headline at the top, left-aligned: "2 am. Brain won't stop." in a heavy white sans-serif, very large`.
- **Few words:** headline 2–8 words, subline ≤ 10, CTA 1–4. Up to 3 text blocks per ad. Text on ≤ ~20% of the canvas (Meta no longer rejects more, but text-heavy statics deliver worse).
- Say what text is **not** there: "The only text in the image is: …". Otherwise the model adds signs, labels and fake brand names.
- Another language: the prompt in English, the text in quotes in that language, written by you (not machine-translated word for word).
- Numbers, prices, ratings, offers: only from the Brand Kit or the user.
- **Check every letter with the user** after the run. One wrong letter → rerun naming the right spelling ("the button reads exactly 'Try it tonight'"). Two failed reruns → generate the image with that zone left clean and tell the user to set the text in their design tool (Figma), or move the text to a typography-led model (Reference A).
- Fonts: describe the style ("heavy geometric sans-serif", "handwritten marker"); the brand font name helps when the Brand Kit has one, but exact font matching isn't guaranteed: say so once if the user expects pixel-exact brand type.
## Realism (Nano Banana Pro)
**Nano Banana Pro is our model for the most realistic images.** Every photo-real final (people, rooms, hands, phones, products) is made on Pro at 2K or 4K. Drafts on Nano Banana 2 or Nano Banana are fine for direction, but realism and text are judged only on Pro.
**Realism is coherence, not detail.** Light explains form, materials react to light, the pose obeys anatomy, the camera matches the distance and the composition. "Photorealistic", "ultra realistic", "8K" only state intent; describe the **observable signs of a photograph** instead. When everything serves one scene, the image starts to feel like a real frame.
**Decide first: what camera "took" this photo?** Two families, never mixed:
- **Phone-real (UGC, native, most app ads):** "shot on a 24mm smartphone camera", deep focus with a sharp, readable background, the light that is really there (lamp, window, phone screen, car daylight), slight noise in low light, casual off-center framing, no grading. Portrait bokeh reads as a camera ad, not a phone.
- **Camera-real (lifestyle, editorial, product, campaign):** a lens and its perspective (35mm environmental, 50mm natural, 85mm portrait, macro for detail), controlled depth of field with a reason, one main light with a named source, restrained grading, subtle grain.
**The formula** (in this order): scene and action → appearance and styling → location → composition → camera → light → materials → color and finish → mood → targeted exclusions.
**What makes it real (short):**
- **Skin:** natural tone variation, fine pores, soft texture, natural creases, real asymmetry, live expression; makeup named separately (bare skin, sheer, editorial). Highlights on raised areas, shadows in hollows, no lacquer. Never "flawless", "perfect", "porcelain", "glowing".
- **Light:** one main source with a direction and a reason ("soft overcast daylight from a window at camera left"); shadows and reflections on clothes and background follow it; contact shadows under chin, feet, objects and folds. Don't mix sources without saying where each comes from.
- **Optics:** the lens fits the distance (no wide lens for a close portrait); shallow depth only on purpose; natural focus falloff, natural bokeh, mild optical imperfection.
- **Materials:** name the substance and how it behaves: silk (long soft highlights), cotton (matte, visible weave, creases), leather (uneven sheen, bends), metal (clean reflections), glass (thickness, refraction, edge highlights), concrete and stone (pores, wear, color variation). Pick 2–4 materials that will be visible.
- **Physics:** one phase of one action ("mid-stride, weight shifting onto the front foot, the coat hem swinging"); hair, fabric and objects obey the same movement; a hand visibly touches what it holds.
- **Places:** lived-in, 2–3 specific details that tell the story; never a showroom or an empty minimalist room (unless that is the concept).
- **Edges of the frame:** no randomly cut hands, feet or objects; the crop looks chosen.
**Exclusions:** the Lyra image node has no negative field, so describe the wanted state first ("natural skin texture, subtle pores" rather than only "no plastic skin"), then one short, scene-specific "Avoid …" line at the end. Only the risks of this scene, not the whole list.
The full realism toolkit (skin, light setups, lens table, materials, phrase bank, fixes table, worked prompts, checklist): Reference D.
## Styles
The style comes from the brief and the Brand Kit, not from habit. Choose **one leading style + at most one supporting influence**, and describe it in words (if you name an artist or a director, also describe the look; the model needs the description, and the name can be refused). Full table with cues and risks: Reference C.
| Family | Styles | Default model |
|---|---|---|
| **Photo-real** | UGC phone photo · lifestyle candid · documentary / street · studio product · commercial lifestyle · editorial / fashion · cinematic still · analog film | Nano Banana Pro |
| **Designed** | in-app proof shot · typographic · collage / mixed media · infographic / data · apparent screenshot / native post · retro (Y2K, office-core, 90s print) | Nano Banana Pro (Ideogram 3.0 to test for type-led) |
| **Illustrated** | flat vector · hand-drawn / doodle · watercolor · kawaii · comic / anime-inspired (original characters) · clay / soft 3D · 3D render | Nano Banana Pro; Flux 2 / Wan 2.7 Pro as alternatives to test |
| **Surreal / metaphor** | minimal surrealism · hyperbole (giant notification, tiny person in an inbox) · impossible scale | Nano Banana Pro, photo-real execution |
## Best way to build it
The user's explicit choices override any row. Model choice: Reference A.
| If the request has | Best approach (graph) | Models | Why |
|---|---|---|---|
| **Nothing specific (default)**: 1–4 static ads | concept card → one Pro node per concept, 4:5, 2K, whole layout and every text in the prompt; logo / screenshot uploads as references | nano-banana-pro | fewest nodes; Pro renders people, text and UI best |
| The same person in several images (carousel, series, video later) | persona node first (count 2, user picks) → connected as reference to every image with the person | nano-banana-pro | consistency comes from the reference, not from text |
| The app's UI in the ad | screenshot uploads → in the ad prompt, the screen "exactly as supplied" + key texts in quotes; a separate phone-shot node when the screen is the hero or keeps failing | nano-banana-pro | the UI is never redrawn (Reference G) |
| Carousel | one node per card, same anchors (palette, type, persona, background) word for word; card 1 = hook; last card = CTA | nano-banana-pro | one look across cards |
| Many directions / tight budget | drafts on nano-banana-2 at 1K, count 2–3 → the user picks → winners rerun on Pro at 2K | nano-banana-2 → nano-banana-pro | spend on the winners |
| Text-heavy or type-only poster | Pro first; if a block keeps failing, an Ideogram 3.0 Quality test, or a clean zone for the designer | nano-banana-pro · ideogram-v3-quality | exact type |
| Transparent cutout, sticker, element for the designer | GPT Image 2, `background: transparent`, 1:1 / 3:2 / 2:3 | openai/gpt-image-2 | the only listed model with transparency |
| Edit an existing image (swap person, change one element, relight) | the source image connected → Pro, "change only…" prompt | nano-banana-pro | keeps everything else |
| A reference static to adapt (competitor's static, carousel, several statics, a key frame of their video) | `lyra-copy-competitor-static` → built on this skill's rules | nano-banana-pro | keeps the mechanism, not the identity |
| Other ratios of an approved ad | `lyra-adapt-image` (Image Resize, Nano Banana 2) for simple layouts; a Pro **recompose** node with the ad connected when the layout or text must move | nano-banana-2 · nano-banana-pro | recompose, don't crop |
| Other languages | Image Translation (Nano Banana 2) for ads without UI; ads with UI → localized screenshots + text written in that language, new Pro node | nano-banana-2 · nano-banana-pro | the UI is never machine-translated |
| An animated version of the winner | the approved image as first frame → `lyra-ui-motion-video` (UI-led) or `lyra-video-ad-generation` | seedance-2.0 / 2.5 | the static becomes a keyframe |
**Lyra image nodes and the tools.** Lyra has image actions `image_generation`, `character_generation`, `product_screen_placement`, `change_element_on_image`, `image_resize`, `image_translation`, `upload_image`. The MCP tools create **Image Generation** (`create_image_generation_node`), **Image Resize** and **Image Translation** nodes; Character Generation, Product Screen Placement and Change Element come only from templates or the user's canvas (then `update_node` their prompt). Without them, an Image Generation node with the right images connected and a prompt written by their rules does the same job (Reference E, G, F).
## Prompt rules
| Node | Write | Avoid |
|---|---|---|
| Concept card (text) | hypothesis, visual, layout map with exact texts, style, palette, text count | prompts meant for the model; claims not in the Brand Kit |
| **Static ad** (image) | format and ratio in words ("static app ad, vertical 4:5") → each reference's job ("[Image1] is …") → the scene: subject, action, place, camera, light, materials (Realism) → **layout top to bottom** with every text in quotes, style, color, size → the screen "exactly as supplied" + its key texts, if any → palette (Brand Kit hex) → style line → "The only text in the image is …" → short "Avoid …" | "like the reference"; "8K, masterpiece, hyper-realistic"; extra text; generated logos, badges, UI; two promises |
| Photo (no layout) | the realism formula: scene and action → appearance → location → composition → camera → light → materials → color and finish → mood → targeted exclusions | keyword stacks; contradicting lights; "flawless" |
| Persona | "UGC phone photo" or the chosen style → the character card word for word → in the pain place, mid-moment → looking into the camera (selfie / front POV) unless the scene needs otherwise → framing by shot and ratio → realism line → no text | model-like posing; stereotypes; a real person or lookalike |
| Phone shot / product shot | each input's job → device and how it's held or placed → fidelity line → key texts in quotes → backdrop → soft controlled reflections → screen front-facing, large | phone brand logos; fingers or glare over text; strong tilt |
| Edit | strong verb first ("Replace", "Change", "Remove") → what stays exactly (person, pose, framing, light, phone, text) → the one change, concrete → realism → no new text | re-describing the whole scene; two changes at once |
| Carousel card | the shared anchors word for word → this card's role and layout → its text | a different palette, type or persona per card |
| Illustration | the style described fully (line, fill, texture, palette, character proportions) → the scene → layout and text | naming a living artist as the only style cue; known characters |
**Prompt length:** a photo 60–150 words; a full static ad with layout and texts 100–220 words. Over ~250 words, later details get lost: cut adjectives before cutting layout or text. Non-negotiables (identity, the screen, the exact texts) early.
**The 6 rules that matter most here:** (1) one promise, one focal point; (2) the layout map with zones and exact texts, in the prompt; (3) every text in quotes, and "the only text in the image is…"; (4) logo, icon, badges and UI only from uploads, exactly as supplied; (5) realism through observable photographic signs and one coherent light, on Nano Banana Pro; (6) check every letter and every screen with the user before anything is built on the image.
**Pattern: static ad, photo-real with UI (Nano Banana Pro, 4:5).**
> Static app ad, vertical 4:5, UGC phone-photo style. [Image1] is Mia: her face, curly hair in a loose bun, grey hoodie. [Image2] is the app screen. Mia, 21, lies on her side in a dark bedroom at 2 am, holding a modern smartphone toward the camera, screen facing us almost straight on, her thumb at the lower edge away from any text. The phone screen displays [Image2] exactly as supplied: preserve the layout, typography, icons, colors and every word and number; visible on screen: "Tonight's plan", "5 min", "Start". Shot on a 24mm phone camera, deep focus, warm bedside lamp from the right, cool phone light on her face, natural skin texture, visible pores, slight dark circles, rumpled grey duvet, a charger cable and a half-empty glass of water on the nightstand. Layout from top to bottom: top 22%, on the dark wall: headline "2 am. Brain won't stop." in a heavy white sans-serif, very large, left-aligned · middle: Mia and the phone · bottom 15%: a rounded button "Try it tonight" in violet #8B7CF6 with white text, centered. The only text in the image is the headline, the button and the phone screen. Avoid: beauty filter, studio lighting, extra text, logos, warped fingers.
**Pattern: realistic portrait, no layout (Nano Banana Pro).**
> Photorealistic environmental portrait of an adult man in a simple off-white shirt, seated near a window in a lived-in apartment, a candid pause between moments, relaxed shoulders and a natural expression. Eye-level camera, medium close-up, 50mm lens perspective. Soft side daylight with a gentle shadow transition and subtle reflected fill from the room. Realistic skin texture, slight under-eye detail, individual hair strands, natural cotton weave and believable folds. Neutral warm-gray palette, understated documentary feel, authentic photographic tonality. Avoid beauty-filter skin, exaggerated bokeh and artificial symmetry.
**Pattern: edit, one change (Nano Banana Pro).**
> Change only the light. [Image1] is the approved ad: keep the woman, her face, pose, the phone and its screen, the framing, the headline "2 am. Brain won't stop." and the button "Try it tonight" exactly. New light: early morning daylight through half-closed blinds from the left, soft stripes across the duvet, the lamp off. Natural skin texture. No new text.
## Consistency across a series
- **Anchors** written once in the concept card and repeated word for word in every prompt of the series: persona (age, face, hair, skin, outfit), place (room, time, light direction and color), style (production type, palette hex, grading, lens feel), type (headline font style, color, position), device (generic modern phone, case color).
- **Images over words:** the persona, the product shot and any style sample are connected as references to every image that needs them. State each reference's job; an unassigned reference leaks its light or framing.
- One model for the whole series (Pro); one ratio per set; the same resolution.
- In a carousel or A/B set, change only what the test changes; list what's held constant (Lyra's Ad Variation rule).
- Details: Reference E.
## Common mistakes (this skill)
| Mistake | Prevention |
|---|---|
| Two promises or two heroes in one static | One promise, one focal point; the second idea is a second ad |
| Layout left to the model | Layout map with zones, shares and exact texts in the prompt |
| Text garbled, extra words, fake signs | Quotes, few words, "the only text is…"; check every letter; clean zone after two fails |
| Generated logo, icon, store badge or rating | Uploads only, exactly as supplied; real numbers or none |
| UI redrawn or "improved" | Screenshot connected, fidelity line, key texts in quotes, word-by-word check (Reference G) |
| Plastic skin, glossy everything, stock look | Realism section; phone-real for native ads; no "flawless, 8K, masterpiece" |
| Portrait bokeh on a "phone photo" | Phone-real = deep focus, sharp background |
| Light that doesn't match (face lit from the left, shadows to the left) | One named source; shadows and reflections follow it |
| Text over a face, hands or the screen | Clean zones in the layout map; contrast band if needed |
| A crop for another ratio cuts the headline | Recompose for the new ratio; check safe zones |
| Image Translation on an ad with UI | Localized screenshots + text written in that language |
| Persona changes between carousel cards | Persona node connected as reference to every card; same anchors |
| Draft model's result judged as final realism | Realism and text judged only on Pro |
| "Like the reference" in a prompt | Describe the layout and style in words; references only with a stated job |
| Transparent background asked on Pro | GPT Image 2 with `background: transparent` |
## Quality gates
After each intermediate stage Claude sends the stage checklist (the final images are checked by `lyra-result-check`) and asks the user what they like and what they don't (Reference J has the full slop list):
- **Stage 0 (concept, Claude checks before sending):** one promise and one focal point per ad? Layout map with zones and every text word for word? Text short (headline ≤ 8 words, ≤ 3 blocks)? Claims, numbers, offer traced to the Brand Kit? Real screens only, logo from the upload? Style and model stated with why? Safe zones for the ratio?
- **Stage 1 (persona, product, phone shot):** looks like a real person photographed (skin, hair, hands)? Place lived-in? Screen identical to the screenshot, word by word? Style right?
- **Stage 2 (ads):** at phone size (shrink it or look from a distance), does it read in half a second: what it is, for whom, what to do? Every letter and number right, nothing extra? Light, shadows and reflections coherent? Hands, fingers, phone natural? Logo exact and small? Text clear of faces and the screen, inside the safe zone? One CTA? On brand?
- **Stage 3 (sizes, languages, variants):** nothing cropped, headline and CTA inside safe zones, text re-checked in every language, the intended difference visible between variants, files named.
Pass = the user is happy with every point that applies. Fix only what fails, within the agreed budget, with its credits.
## Truth and disclosure
- No invented claims, numbers, ratings, awards, pricing, user counts, reviews or results. A claim may appear only if it is in the inputs (Brand Kit or the user): "clinically tested" in the kit can be used; not in the kit, it can't. Testimonial cards only with real reviews from the Brand Kit, attributed as reviews.
- **Brand safety** (Lyra's System Preamble): nothing that could damage the advertiser's reputation; no profanity, no political statements, no unsubstantiated health claims, no competitor disparagement (an old way vs app comparison never names or mocks a competitor). The Brand Kit's **forbidden claims are enforced absolutely**: they never appear in a headline, a subline, a chat bubble or a visual; if the user asks for one, say once that it is on the kit's forbidden list and leave it out unless the user confirms the kit is outdated.
- An AI person is a creative scene, never a real customer, a verified user or a real expert; no credentials the persona doesn't have (white coat, "Dr."). No body before/after for health or weight-loss apps.
- No real people, celebrities, creators or lookalikes; no known characters, mascots or memes the user doesn't own; no third-party logos or brand marks on clothes, phones, cars or shelves; no copies of iOS, WhatsApp, Instagram or system UI (stylised bubbles and cards only).
- Platforms label AI content: tell the user once, in the final report, to turn on the AI label where the platform asks for it for photorealistic synthetic people. Not legal advice; they check current platform rules.
## Deliverable and naming
1. A "Concept card" text node per concept (or one for the set).
2. Uploads, persona / product / phone shots, the ads, sizes and languages, each labelled.
3. Names: `B{batch}-A:{angle}-F:Static-{format}-C{concept}-{ratio}` (+ `-{lang}` for other languages, `-V{n}` for variants), e.g. `B4-A:2amBrain-F:Static-PainPOV-C1-4x5`, `B4-A:2amBrain-F:Carousel-C2-card3-4x5`.
## After the test
Statics fatigue fast at scale (often 7–14 days): plan refreshes. Read a test by the goal's cost per result (trial, payer), not CTR alone; give it enough conversions before calling a winner. Then offer: variants of the winner one variable at a time (the headline, the visual hook, the person, the proof), other sizes (recomposed), languages, an audience version (`lyra-audience-variations`), new angles (`lyra-ad-concept-multiplier`), or an animated version of the winner (the image as first frame).
---
# Reference library
## A. Image models, settings and price
Always call `list_node_configs` first: it is the live source of image models, ratios, resolutions and actions. **New models will be added**: when a new image model appears, offer it only for what its config and the user's tests show it does well, and keep Nano Banana Pro as the default for realism until the team says otherwise.
**How to offer a model.** Recommend **Nano Banana Pro** for every final, and say plainly: "This is our best model for realistic people, text and UI; it costs more than the drafts, but it gives the best result." Give the cost in the plan (Credit prices below). Always ask which model the user prefers before building.
**Model cards (Lyra, Oct 2026)**
- **★ Nano Banana Pro** (`google/nano-banana-pro`, Google's Gemini 3 Pro Image): **the default for finals and the most realistic frames.** Best in Lyra for photo-real people, skin, hands, rooms, product and phone shots, on-image text, real UI placed from a screenshot, and edits that keep everything else. Resolution 1K / **2K (default)** / 4K; ratios match_input_image, 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9. Takes many reference images (Google's guide: up to 14 in one prompt); keep the set small and give each a job. ~35–50 s per image.
- **Nano Banana 2** (`google/nano-banana-2`, Gemini 3.1 Flash Image): **drafts**, and the default model of Lyra's Image Resize and Image Translation nodes. 1K / 2K / 4K; all Pro ratios plus extreme ones (1:4, 4:1, 1:8, 8:1) for banners and strips. Faster and cheaper; realism and text are checked again on Pro.
- **Nano Banana** (`google/nano-banana`, Gemini 2.5 Flash Image): the original, cheapest and fastest; no resolution setting. Quick tries, simple edits, high volume.
- **GPT Image 2** (`openai/gpt-image-2`): the only listed model with **transparent background** (`background: transparent`): cutouts, stickers, elements for designers. Ratios 1:1, 3:2, 2:3 only. Slow (up to ~90 s).
- **Ideogram 3.0** Quality / Balanced / Turbo (`ideogram-ai/ideogram-v3-*`): typography-led designs and posters; a test option when a text block keeps failing on Pro. Many ratios (1:3 to 3:1) and fixed pixel sizes.
- **Flux 2** Pro / Max / Flex (`black-forest-labs/flux-2-*`): alternatives for photo and stylized looks; Max allows a custom ratio and up to 4 MP. Offer when the user asks or wants a second look to compare.
- **Wan 2.7** / **Wan 2.7 Pro** (`wan-video/wan-2.7-image*`): alternatives; Pro up to 4K (4096×4096) with fixed sizes. Offer when the user asks.
**Task → model:** realistic people, UGC photos, lifestyle, product, phone with real UI, text on the image, edits → Nano Banana Pro · drafts, directions → Nano Banana 2 (or Nano Banana) · resize, translation → Nano Banana 2 (Lyra's default) · transparent cutouts → GPT Image 2 · type-only poster that keeps failing → Ideogram 3.0 Quality test · a second look to compare → Flux 2 Pro / Max.
**Settings in the Image Generation node:** model → aspect ratio (the placement: 4:5 Feed, 9:16 Stories / Reels, 1:1 square; `match_input_image` when editing an image) → resolution (2K; 4K for small text, UI to read, close-up skin) → count (1; 2 for the hero or persona when the user wants a choice) → references connected with their job written in the prompt.
**Cheaper ladder** (one step at a time, show the new price): Pro 4K → Pro 2K → Pro 1K → Nano Banana 2 2K → Nano Banana 2 1K → Nano Banana. Drafts first, finals later: test directions cheaply, rerun only the winners on Pro.
**Credit prices** (Lyra, Oct 2026; credits per run, rounded up; a node's `credits` in `get_workflow` is always the final word):
| Node | Price |
|---|---|
| Nano Banana Pro 2K | 23 per image (1K and 4K not measured yet: read the node) |
| Nano Banana 2 1K | 11 per image |
| GPT Image 2 | 20 per image |
| Ideogram 3.0 Turbo | 5 per image |
| Image Resize (Nano Banana 2, 1K) | 11 per target ratio |
| Image Translation (Nano Banana 2, 1K) | 11 per language |
| Edit / change element | as one generation on that model |
| AI text node · Text Split · user text, uploads, notes | 1 · 0 · 0 |
Count multiplies the price; the ratio doesn't change it. Example: persona (count 2) 46 + 3 ads on Pro 2K 69 + 9:16 and 1:1 of each by Image Resize 66 ≈ **181 credits**. Models or settings not in the table: build, read the node, then tell the user.
**Reference policy.** A technical maximum is not a target: every extra reference makes the result less predictable. Default references = the user's uploads (logo, screenshots, product photos) and the images you generated (persona, product shot). A style sample only when the user brings one or the series needs one look; then say its job ("[Image3] is a style reference only: copy its palette, light and grain; not its people, objects or text").
## B. Layout library: static formats that work for apps
A reference, not a menu. Each format with its zones (top → bottom for vertical) and a build note.
| Format | Layout | Works for | Build note |
|---|---|---|---|
| **Pain POV photo** (default for cold traffic) | headline (the pain in the audience's words) in a clean top zone · the person in the pain moment, phone-real · small CTA band | most apps | Pro, UGC phone photo; the face carries the pain |
| **In-app proof shot** | benefit headline top · the real screen on a phone, 55–65% of the frame · one high-contrast CTA | apps with a clean UI or a visible result | screenshot connected, fidelity line, 4K |
| **Apparent screenshot / native post** | looks like a note, a story or a post with a short first-person text, styled, not a copy of a real app's UI | Gen Z, habits, productivity | stylised generic UI; no platform logos; never presented as a real user's post |
| **Before / after split** | two panels, same framing and light, a short label on each, CTA under | situations that change visibly (messy → organised, late → on time) | never a body before/after for health apps |
| **Result proof** | the result as the hero (a plan, a chart, a score from the real app) · one line why · CTA | finance, fitness, learning, any app with a visible outcome | real numbers and screens only |
| **Comparison: old way vs app** | two columns or rows: the old way (crossed) vs the app's way; short labels | apps replacing a habit or another tool | no competitor names or logos |
| **Listicle / reasons why** | "3 reasons…" headline · 3 short rows with small icons or mini-scenes · CTA | feature-rich apps, considered purchases | ≤ 3 rows, ≤ 6 words each |
| **Chat / comment card** | stylised bubbles: the user's question in their words, the app's warm answer · CTA | coaching, health habits, learning, finance | stylised bubbles, no WhatsApp / iOS copy; fictional chat never shown as real |
| **Review card** | a real review quote large, stars only if real, the reviewer's first name as in the review · CTA | warm traffic, trust categories | only real reviews from the Brand Kit |
| **Starter pack / grid** | "The [audience] starter pack" · 4–6 objects of their life, the app as one of them | lifestyle, habits, hobbies | objects generic, no brand marks |
| **Visual metaphor / hyperbole** | one impossible image of the pain (a giant notification crushing the desk) · short headline | unaware audiences, scroll-stopping | photo-real execution of the impossible; one idea |
| **Big question / statement** | type is the hero on a brand color or a texture · small CTA | bold brands, sound-off feeds | every line in quotes with its style |
| **Offer card** | the offer large ("7 days free") · the app icon (upload) · the product moment small · CTA | warm traffic, real risk reversal | offer from the Brand Kit only |
| **Mascot / illustrated story** | the brand's own mascot in one scene of the pain → fix · headline · CTA | brands with a mascot, kids & family, casual | the brand's mascot as reference; style described |
| **Lo-fi / meme-like original** | deliberately simple, a relatable caption over a scene | Gen Z, casual apps | original format only, never a copyrighted meme image |
**Ratios and placements (Meta):** Feed 4:5 (1080×1350) preferred for direct response, 1:1 (1080×1080) works · Stories / Reels 9:16 (1080×1920), keep the top ~250 px and bottom ~340 px clear of key content · ship 1:1, 4:5 and 9:16 for a full set, each **recomposed**. Check the current specs in Meta's guide before export; they change.
## C. Styles: cues and risks
| Style | Cues for the prompt | Risk to avoid |
|---|---|---|
| UGC phone photo | shot on a 24mm smartphone camera, deep focus, motivated light, casual off-center framing, slight noise in low light, no grading | portrait bokeh, studio light, beauty filter |
| Lifestyle candid | candid moment, available light, 35mm, natural color, unposed gesture | stock-photo smiles, everything clean |
| Documentary / street | documentary photography, available light, real street depth, subject slightly off-center, muted urban colors | frozen mannequin pose, glossy CGI surfaces |
| Studio product | controlled studio lighting, large softbox, bounce card, seamless backdrop, precise shadow shaping, accurate geometry, natural contact shadow | floating objects, impossible reflections, warped lettering |
| Commercial lifestyle | soft directional light, brand palette, clean but lived-in, 50mm | glossy over-saturation |
| Editorial / fashion | high-end fashion editorial, art-directed styling, sculptural pose, 85mm, restrained contrast, subtle grain | waxy skin, impossible garments |
| Cinematic still | cinematic still, motivated practical lighting, restrained color grade, atmospheric depth | teal-orange cliché, haze over the face |
| Analog film | subtle film grain, gentle highlight roll-off, organic color response | fake light leaks everywhere |
| In-app proof / tech | the phone large and front-facing, brand gradient or clean backdrop, controlled glass reflections | fake UI, phone brand logos |
| Typographic | the type described line by line, brand color field or paper texture, generous margins | more than 3 text blocks |
| Collage / mixed media | cut-paper edges, photo + paint + type, layered, slightly imperfect | chaos without a focal point |
| Flat vector | flat shapes, limited palette (brand hex), clean outlines, no gradients or soft gradients | generic corporate "Alegria" people |
| Hand-drawn / doodle / watercolor | visible strokes, paper texture, soft washes, imperfect lines | mixing with photo realism |
| Kawaii / cute | soft pastel palette, round shapes, big expressive eyes, simple backgrounds | known characters |
| Clay / soft 3D | soft clay material, rounded forms, studio light, tactile surface | plastic CGI look when "real" was asked |
| Retro (Y2K, office-core, 90s print) | era-true materials, colors and type, a slight print or screen texture | real logos of the era's brands |
| Minimal surrealism | one impossible idea, photo-real execution, calm composition | stacking several surreal ideas |
## D. Realism toolkit
**Principle:** frame first, beautiful words later. Before writing, decide: the main subject · the action and the exact moment · the place · camera and composition (shot size, height, distance, perspective, placement) · light (source, direction, softness, contrast, color temperature) · materials and textures · mood.
**Universal formula:** [main subject] + [concrete action] + [appearance / styling] + [location] + [composition and angle] + [a logical light source] + [physical textures] + [color and mood] + [photographic character] + [what to exclude].
Short daily version: **SCENE + ACTION + STYLING + LOCATION + COMPOSITION + CAMERA + LIGHT + TEXTURES + COLOR + MOOD + TARGETED EXCLUSIONS.**
**Skin and face:** natural unevenness of tone, fine pores, soft texture, natural folds and micro-details · real asymmetry (small differences between the sides, live expression, natural line of lips and eyelids) · makeup type stated separately (bare skin, sheer makeup, editorial makeup) · no over-retouching, waxy smoothness, uniform shine or over-sharp pores · skin reacts to light: highlights on raised areas, shadows in hollows, no lacquer effect.
**Light setups:** natural daylight: soft window light, overcast daylight, late-afternoon sunlight · studio: large softbox, beauty dish, strip light, bounce fill, controlled shadow falloff · cinematic: motivated practical lighting, warm practical lamps, cool ambient fill, subtle rim light · phone-real: bedside lamp, phone screen glow, car daylight, office fluorescent, bathroom mirror light. Don't mix many sources without saying where each comes from. Ask for natural contact shadows under the chin, feet, objects and fabric folds.
**Optics:** 24mm wide interiors and dynamic perspective (watch edge distortion) · 35mm reportage, environment visible, close involvement · 50mm universal, natural sense of space · 85mm classic portrait, calmer perspective, background separation · macro for tiny details. A close portrait on a wide lens distorts features. Shallow depth of field only with a reason; real optics allow soft focus falloff, natural bokeh, mild imperfections. Camera and lens names are guidance, not magic commands.
**Materials:** silk (soft elongated highlights, fluid folds) · cotton (matte, visible weave, natural creases) · leather (uneven sheen, fine grain, bends where it moves) · metal (clear environment reflections, controlled highlights, believable edges) · glass (reflections and refraction, visible thickness, edge highlights) · stone and concrete (surface variation, small pores, wear, color differences) · phone (glass screen reflections controlled, matte case, no fingerprints over text).
**Motion and physics in a still:** the phase of the action stated (a step at the moment of weight transfer, fabric in flight, hair answering the wind, drops with a clear direction); body, clothes, hair and objects obey one movement; no incompatible simultaneous movements.
**Photographic language (a few precise tags, not dozens):**
| Task | Phrases |
|---|---|
| Fashion campaign | high-end fashion editorial, art-directed styling, sculptural pose, luxury campaign |
| Live reportage | documentary photography, candid moment, available light, unposed gesture |
| Clean studio | controlled studio lighting, seamless backdrop, precise shadow shaping |
| Cinematic atmosphere | cinematic still, motivated lighting, restrained color grade, atmospheric depth |
| Analog photo | subtle film grain, gentle highlight roll-off, organic color response |
| Catalog product | accurate product geometry, clean reflections, precise material rendering, commercial product photography |
| Natural portrait | natural skin texture, realistic catchlights, relaxed expression, believable lens perspective |
| UGC phone photo | shot on a 24mm smartphone camera, deep focus, natural window light, casual, unpolished, no beauty filter |
**Composition:** one main point of attention, the rest supports it · shot size named (extreme close-up, close-up, waist-up, full body, wide environmental portrait) · placement named (centered, off-center, profile, three-quarter view, looking away) · foreground, middle and background when depth matters · negative space when the frame must work as a cover or an ad layout · watch the edges: cut hands, feet, accessories and objects break the feeling of a planned shoot.
**Exclusions bank** (pick only this scene's risks): waxy skin, excessive beauty retouching, plastic texture, uncanny facial symmetry, malformed hands, extra fingers, duplicated limbs, distorted anatomy, floating objects, inconsistent shadows, impossible reflections, warped geometry, over-sharpening, oversaturated colors, fake HDR, excessive bokeh, random text, watermark, logo artifacts. Negative wording doesn't always work literally: also describe the wanted result ("natural skin texture, subtle pores, realistic tonal variation").
**Fixes:**
| Problem | Change |
|---|---|
| Skin looks plastic | Less gloss and retouch; describe pores, tonal variation and natural light |
| Looks like a 3D render | Photographic context, real light sources, contact shadows, physical materials |
| Too many details, chaos | One main subject, one idea of light, a limited palette |
| Face or body unnatural | Simpler pose, a named angle, natural weight distribution, no complex twisting |
| Light doesn't add up | One main source; explain the reflected or back light |
| Background steals attention | Simpler surroundings, lower background contrast, precise depth of field |
| Everything over-sharp | Natural sharpness falloff, soft detail roll-off, moderate processing |
| Too glossy | Replace "luxury / ultra detailed" with concrete textures, calm contrast, restrained grading |
| Text garbled | Fewer words, quotes, size and position named, "the only text is…"; clean zone after two fails |
| Hands wrong | One simple hand action, one object, hand visibly touching it, fewer visible fingers |
**Workflow:** one idea ("quiet luxury in overcast daylight", not cyberpunk + vintage + baroque) → subject and action → composition and camera → light (source and direction; shadows and reflections follow) → 2–4 materials → the image's character (documentary, editorial, studio product, cinematic still) → targeted exclusions → generate a few takes and compare composition, light and believability, not only overall appeal → change **one group of parameters at a time** (composition, then light, then materials or color) → fix locally with an edit, keeping what worked.
**Worked prompts:**
- *Product photo:* "Premium product photograph of a clear glass perfume bottle with a brushed metal cap on a pale travertine surface. Three-quarter product view, carefully controlled reflections, softbox key light from camera left and a subtle white bounce card on the right. Physically plausible glass thickness, clean refraction, accurate label alignment, natural contact shadow and realistic stone pores. Minimal luxury campaign, warm neutral palette, high detail without oversharpening. No duplicated cap, no warped lettering, no floating object, no impossible reflections."
- *Street candid:* "Candid street-style photograph of an adult woman crossing a quiet European city street after light rain, wearing a long trench coat and worn-in leather loafers. Mid-stride, weight visibly shifting onto the front foot, coat hem responding naturally to motion. Shot from sidewalk height with a 35mm lens, subject slightly off-center, real street depth and understated background activity. Overcast daylight mixed with soft reflections from wet pavement, consistent shadow direction, natural skin and fabric texture. Muted urban colors, documentary fashion mood, authentic camera rendering, no glossy CGI surfaces or frozen mannequin pose."
- *Editorial portrait:* "A high-end fashion editorial portrait of an adult woman wearing a sharply tailored charcoal wool coat and minimal silver earrings, standing beside a large rain-streaked window in a quiet modern apartment. Three-quarter portrait, camera at eye level, natural relaxed posture, subtle asymmetry in the expression. Soft overcast daylight from camera left, believable falloff and delicate shadows across the face. Natural skin texture with fine pores and subtle tonal variation, realistic individual hair strands, visible wool fibers and naturally formed fabric creases. 85mm portrait lens, restrained depth of field, crisp focus on the eyes, soft but legible background. Muted charcoal, stone and cool beige palette, refined filmic color, subtle grain, realistic highlight roll-off. No waxy skin, no excessive retouching, no distorted hands, no artificial halo lighting, no over-sharpening."
**Pre-generation checklist:** main subject clear? Action or pose concrete? Place clear and background logical? Shot size, angle and composition set? Light source clear, and shadows and reflections match it? Skin, fabric and key materials described? Lens, distance and perspective agree? Palette and mood serve one idea? Exclusions specific to this scene? Any words that add no visual information (cut them)?
## E. Persona and consistency
**Persona (Lyra's Character Generation and Character Brief rules).** If the canvas has a Character Generation or Character Brief node, `update_node` its prompt; otherwise a Pro Image Generation node written to the same rules:
- Exact identifiers: age range, gender, ethnicity, hair (color, length, style), face details with small imperfections, build, distinctive marks. Clothing is the main consistency anchor.
- Natural, not model-like; slightly imperfect; looks directly into the camera (selfie or front POV) unless the scene needs otherwise; in a believable real place tied to the product context; feels like a real person from Stories or TikTok.
- Framing by shot: full body (lifestyle, action, with footwear) · waist up (conversational, product holding, testimonial) · close-up (emotional hooks, reactions). Framing by ratio: 9:16 person in the central 65% with space for text top and bottom · 4:5 and 1:1 waist up, centered · 16:9 off-center on the thirds.
- Expression by the moment: caught or excited for a hook, tired or annoyed for the problem, relieved for the solution.
- No text in the persona image. No stereotypes, no real people or lookalikes; adults only as the speaking or main persona.
- Character card written once, repeated word for word: "Mia · 21 · student · light brown skin, freckles, dark curly hair in a loose bun · no makeup, slight dark circles · oversized grey hoodie, thin silver hoops".
**Across a series:** the persona image connected as reference to every image with the person ("[Image1] is Mia: use her face, hair and hoodie"); the place, light and style anchors repeated word for word; the same model and ratio. **When it drifts:** move the identity line to the start, shorten the prompt, simplify the pose; a reference leaking light or framing → state its job or drop it; after two fails, regenerate the persona with a clearer front view and reconnect.
## F. Edits and swaps
Edits keep what works and change one thing. Pro, the source image connected, `match_input_image` ratio.
- **Verb first**: Replace, Change, Remove, Add, Relight, Recompose.
- **Keep list** before the change: person, face, pose, framing, camera angle, phone and screen, every text.
- **One change per edit**, described concretely (class, age, material, light direction).
- **Person swap:** the original frame + the new persona connected; "replace only the person in [Image1] with the woman from [Image2]".
- **World swap:** change the room, outfit, car, prop or light; "keep the person, face, hair, pose, phone and framing exactly".
- **Recompose for a new ratio:** "Recompose [Image1] for vertical 9:16: keep the person, the phone screen, the headline '…' and the button '…' exactly; extend the bedroom naturally above and below; move the headline into the top clean zone below the top 14%; keep the button above the bottom 20%."
- Check for **bleed** (traces of the old face, outfit or room), hands, the screen and the text. Bleed → "change only…" moved to the start; after two tries, generate fresh with the new element as the only reference for that layer.
## G. App UI, logo and icon in images
Full rules: `lyra-ui-motion-video` (UI fidelity, screens, store sets, end card). The essentials for statics:
- **Never invent or change anything in the UI.** Screenshots only (never a screen recording), current version, full resolution; no screenshot → the screen faces away, is dark or out of frame.
- In the prompt: each input's job ("[Image2] is the app screen") → "The phone screen displays [Image2] exactly as supplied: preserve the layout, typography, spacing, icons, colors and every word and number; do not redesign, simplify, translate or add anything" → the 3–5 key visible texts in quotes.
- Phone almost front-facing (tilt up to ~15°), screen large (half the frame height or more for a read moment), generic modern phone without a brand logo, no fingers or glare over text, 4K when the screen must be read.
- **Check word by word with the user** before anything is built on it. A wrong letter → rerun naming the right text. After two fails: larger screen, simpler pose; still failing → the clean screenshot placed flat (as a card, not in a hand), or the screen left for the designer.
- A blurry screenshot: ask for sharper originals; otherwise improve it on Pro ("Upscale and sharpen this app screenshot. Keep it exactly as supplied…") and check it word by word before use.
- **Logo and app icon:** only the uploaded files, connected as references, "place the logo from [Image3] exactly as supplied, small, bottom-right"; check it; if it warps, leave the corner clean for the designer. Store badges, ratings, awards: official files and real numbers only; badges are best added by the designer.
- **Image Translation never on images with UI** (it would translate the interface). Other markets = the localized app's screenshots.
## H. Sizes and languages (for `lyra-adapt-image`)
- Other ratios: **recompose, don't crop.** Simple layouts with text far from the edges → Image Resize node (Nano Banana 2, one output per ratio). Layouts where text or the hero must move, or Pro-level realism must hold → a Pro recompose node (Reference F). Check headline, CTA and hero inside the new safe zones.
- Other languages: ads without UI → Image Translation node (Nano Banana 2, one output per language); check every word with a speaker of that language if possible and check length (translations run longer; the layout may need a shorter line). Ads with UI → localized screenshots + the text written in that language, new Pro node.
- Every adapted image is checked again: text, cropping, safe zones.
## I. Errors
| Problem | Fix |
|---|---|
| `validation_error` on a node | update_node with values from list_node_configs (ratio and resolution differ by model) |
| Ratio not available on the model | Pick a listed ratio or a model that has it (GPT Image 2: only 1:1, 3:2, 2:3; Nano Banana: no resolution) |
| Text garbled or misspelled | Fewer words, quotes, size and position, "the only text is…"; rerun naming the right spelling; clean zone after two fails |
| Extra text, fake signs, fake brand names | "The only text in the image is…"; blank surfaces described ("plain wall") |
| UI redrawn or changed | Fidelity line, key texts, larger screen, 4K; flat screenshot card as fallback (G) |
| Logo warped or invented | Upload connected with its job; leave a clean corner for the designer |
| Plastic skin, CGI look | Realism section; phone-real or camera-real cues; remove "8K, flawless, hyper-realistic" |
| Hands and fingers wrong | One simple hand action, one object, visible contact; fewer fingers visible |
| Persona drifts across images | Persona connected to every image; identity line first; same anchors (E) |
| Reference leaks its light, colors or framing | State its job in the prompt or drop it |
| Resize cut the headline | Recompose on Pro, or move the text zone (H) |
| Translation changed the UI | Never translate UI images; localized screenshots |
| Transparent background ignored | Only GPT Image 2 with `background: transparent` |
| Model refused (a real person, a brand) | Tell the user; don't rephrase around it; offer an original persona or generic object |
| Image ignores a reference | Connect it; name it ([Image1]) and give it a job in the prompt |
| Two failed tries | Simplify the concept (fewer elements, fewer words), change one variable, or change the model; never rerun unchanged |
## J. De-slop for images
**Prevent:** style from the brief, not "premium" by default · real skin, real hair, real hands · lived-in places with 2–3 specific details · one light logic · no "stunning, 8K, masterpiece, hyper-realistic, flawless" · one focal point · text short, in quotes, nothing extra · real UI, real logo, real numbers only · a short scene-specific "Avoid …" line.
**Slop signs:** faces (plastic or waxy skin, uncanny symmetry, dead eyes, teeth melting, too-perfect makeup) · hands (extra or merged fingers, a phone held impossibly, fingers through objects) · text (garbled letters, fake words, extra signs, wrong spelling of the app name) · UI and logo (invented screens, changed text, warped logo, generated badges) · light (shadows in two directions, halo, no contact shadows, fake HDR) · scene (floating objects, warped straight lines, impossible reflections, duplicated items) · look (over-glossy, over-saturated, stock vibe, everything perfectly clean, wrong style for the brief) · layout (two heroes, text over the face, CTA outside the safe zone, cluttered).
## K. Static ads on Meta (what works)
- Statics still carry a large share of app spend and are cheap to iterate; video wins for some categories (casual games, dating, social, demos that need motion). Test both; a winning static is also a ready keyframe for a video.
- Native beats designed for cold traffic: phone-real photos, in-app proof shots, apparent posts. Logo-and-headline-only designs and stock lifestyle photos tend to convert worst.
- One promise, one CTA, a hook that names a friction the viewer feels; the subject readable in the first half second (median fixation on a feed static is under 2 s).
- Text on ≤ ~20% of the canvas (the old rule is gone, text-heavy statics still deliver worse). Meta's headline field (separate from the image) ~27 characters.
- Sizes: 4:5 (1080×1350) Feed, 1:1 (1080×1080), 9:16 (1080×1920) Stories / Reels with top and bottom clear; a full set ships all three, recomposed.
- Volume and fatigue: statics at scale often fatigue in 7–14 days; refresh concepts, not only colors. Test one variable at a time inside a concept (headline, visual hook, person, proof), several different concepts across a campaign.
- Judge by trials, payers and day-7 retention, not CTR or CPI alone.
## L. Brand Kit
Every concept, text, prompt and palette is built on the Brand Kit: audience first, then product, value, tone, colors (hex), claims, forbidden claims (enforced absolutely), offer, must include / exclude. Source order: the chat → the kit connected to the workspace / workflow → ask (send it, or check and connect one of the workspace's kits). The user's chat request always wins; the kit fills everything they didn't say; mention a conflict in one line.
lyra-ugc-video60.8 KB
View saved version →
---
name: lyra-ugc-video
description: "UGC style video ads for mobile apps in Lyra, a realistic person talking to the phone camera in a real place, with their own voice and a speech built from the audience's pain, usually opened with a hook from lyra-video-hooks. Use for \"a UGC video\", \"UGC ad for my app\", \"a creator / influencer style ad\", \"talking head\", \"testimonial style\", \"storytime\", \"car vlog\", \"street interview\", \"a skit\", \"day in my life\", \"honest review\", or a Lyra UGC or Talking Head template. Core video rules come from lyra-video-ad-generation."
---
# lyra-ugc-video
This skill makes UGC style video ads for mobile apps; their goal is installs, trials and subscriptions. It casts a believable person from the Brand Kit's audience, puts them where the pain actually happens, gives them a voice that fits, and writes what they say from the audience's real problem. Then builds and runs the video in Lyra.
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**App ads first.** Every decision in this skill serves one goal: the right person installs the app and keeps using it. UGC here is not brand content, a creator portfolio or product UGC for a physical item; it is a performance ad for an app, judged by installs, trials and payers. When a general UGC habit (unboxing, "shop now", a product held up to the camera, an aesthetic mood film) doesn't move an app install, drop it or translate it into its app version (see "UGC for app ads").
**This is a way of thinking, not a script.** The rules below are defaults and good practice. Use judgment: when a different person, place, format or order serves the idea better, do it and say why in one line. Only a few things are fixed: truth (no invented claims, reviews or numbers; an AI person is never a real customer), the Brand Kit's facts, Lyra's technical limits, and the user's explicit choices.
**Base skill first.** Everything not written here follows `lyra-video-ad-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, prompt rules, models (Reference A), audio (C), app UI (D), consistency (E), prompt craft (F), errors (G), de-slop (H), Brand Kit (I), Meta app ads (J). This file only adds what is specific to UGC. If the two disagree, the user wins, then this file, then the base skill.
**Hooks come from `lyra-video-hooks`, and often.** UGC lives or dies in the first 1 to 3 s, so most UGC ads open with a hook built by the hook skill (its pain map, hook kinds, hook base, writing rules). Use it by default, skip it only for the cases in "Hooks in UGC" below. This skill owns the person, the place, the voice, the speech and the body of the video; the hook skill owns the opening.
**Everything comes from the Brand Kit.** The person, the pain, the speech, the feature, the offer, the tone and the look of every UGC video are built from the app's Brand Kit, never from imagination. Source order (base Reference I): the user's words in this chat → the Brand Kit given in the chat → the Brand Kit connected to the workspace or workflow (`list_brand_kits`; one kit → "Make this for {kit name}?", several → ask which) → none: ask once to send it or to connect one of the workspace's kits. The user's request always wins; the Brand Kit fills everything they didn't say; a conflict is named in one line. Missing facts are asked for or written as hypotheses to confirm, never invented. See "What UGC takes from the Brand Kit" in Step 1.
**Model.** UGC and real people talking: **always Seedance 2.5**, references only, 720p by default (1080p on the user's choice), sound on. Never Kling or Veo for UGC; if the user wants cheaper, say faces and speech will lose quality and let them decide (base Reference A).
---
## How to think about UGC
**What it is.** A video that looks like a real person filmed it on their phone and posted it, not like an ad. The viewer should feel they are watching someone like them, or someone they trust, talk about a problem they know. It works because it does not trigger the skip reflex: native, phone-real, personal.
**Four pillars, all built from the audience's pain:**
| Pillar | Question it answers | Comes from |
|---|---|---|
| **Person** (persona) | Who is talking, and why would this viewer listen to them? | the audience segment in the Brand Kit |
| **Place** (setting) | Where and when does the pain happen? | the daily moment in the pain map |
| **Voice** | How does this person sound? | the persona, the market, the tone of voice |
| **Speech** | What do they say, in what words? | the pain, the customer's own words, one real feature |
All four must tell one story. A tired student at 2 am in bed, speaking quietly and a bit hoarse, saying the thing every night owl thinks: that is one idea. A glossy model in a studio saying "this app changed my life" is four mismatched ideas.
**Final test for every UGC concept:** would a real person from this audience post this? Would the right viewer recognise their own problem in 3 s? Is everything the person says true for this app?
**Principles:**
- Problem first, by default. Usually the person starts from the pain, in the audience's words, and the app arrives as the thing that fixed it. This is a default, not a hard rule: naming or showing the app early (app first) is a valid choice when it fits the concept, the audience or the test (see Speech).
- Mirror the viewer. The person looks, lives and talks like the audience (or like the person they trust). Casting is targeting.
- One person, one problem, one feature, one result. No feature lists.
- Talk, don't pitch. Contractions, short sentences, a pause, a half laugh. Copywriting voice kills UGC.
- Specific beats vague: an exact moment ("2 am", "the 15th of the month"), an exact thing ("I opened my banking app and just closed it again").
- Natural beats perfect: casual framing, real rooms, real skin, small imperfections convert better than polish.
- Show, if you talk about it: the pain on the face or in the place; the app only from real screenshots.
**What feels stale in 2026 (avoid unless twisted):** ring-light testimonial · "I've been using this app for a few weeks and…" · forced enthusiasm ("obsessed", "game changer", "life changing") · scripted influencer read · walkthrough with a fake smile · model-perfect actor · a logo intro · "Hey guys". Testimonial-style UGC still takes a big share of budgets but has weakened on cost per trial; tutorial, review and story formats tend to do better for apps.
---
## UGC for app ads: what's different
An app is invisible software on a phone. Product UGC sells something you can hold, open and apply; app UGC has to make an invisible product felt and believed in a few seconds. That changes the job of every pillar.
**Make the app visible, in this order of strength:**
1. **The change on the person.** Stressed → relieved, lost → in control, bored → hooked. The emotional shift is the demo when no screen is shown (the Lyra "Talking head with phone" template works only on this contrast).
2. **The result in life.** What is different after using the app: she sleeps, the fridge is planned, the money is left on the 25th, he speaks to the waiter in Spanish. Show it in the place.
3. **The phone moment.** A thumb taps, she turns the phone a little, she looks at it and reacts; the screen faces her, not us.
4. **One real screen.** The "aha" screen from the user's screenshot, as a short UI insert (base Reference D). Never invented UI, never the full walkthrough.
**App translations of general UGC moves:**
| General UGC | App ad version |
|---|---|
| Unboxing, first impression | **First try:** "I downloaded it last night, ok let's see", the first session, her honest reaction |
| Product demonstration | **One feature, one screen moment**, or the result it gives; ~4 s of real UI at most |
| Before and after (body, skin) | **Before and after of the situation** (the chaos, the bill, the night); never the body for health apps |
| Testimonial | **Creative first-person scene** (never presented as a real user) or real reviews as text |
| "Shop now", "link in bio" | **Install / trial CTA** with the real offer: "it's free for seven days", said like a tip |
| Product held to camera | **The phone held a little toward camera**, screen hidden or a real screenshot |
| Aesthetic product video | Only for premium positioning, and still with a person and a pain |
**The one feature.** Each video sells one job the app does for this person, tied to one pain. A second feature is a second video.
**The ad promise matches the store page.** What the person says and shows (the feature, the offer, the look of the screen) must be what the viewer finds on the App Store or Google Play page and in the first session. Overpromising raises installs and kills trial-to-paid and retention.
**Psychological triggers (pick 2 to 3 per video, not all):**
| Trigger | In an app UGC ad |
|---|---|
| Recognition | the pain moment the viewer lives (2 am, the 15th, the empty fridge) |
| Relief / emotion | the visible shift on the person's face |
| Curiosity | the hook opens a question the body answers |
| Simplicity | "five minutes", "one tap", one feature explained in one sentence |
| Demonstration | one real screen or the result in life, not claims |
| Identity | "someone who has money left", "someone who actually sleeps" |
| Trust | natural delivery, one honest drawback, specific and true details |
| Social proof | only real: real ratings, real review lines as text, real numbers from the Brand Kit |
| Urgency | only a real offer or deadline |
**Positioning sets the polish level.** Read the Brand Kit's positioning and pick one look per video, said in the plan: **raw UGC** (default: handheld, home, casual; most cold traffic) · **elevated UGC** (premium or wellness apps: cleaner rooms, nicer light, still a real person on a phone, still natural skin) · **stylized UGC** (a hook-led or format-hook ad: object POV, surreal fourth wall, from the hook skill). A strong test set for one concept is often the same idea in two of these looks.
**Category guide (starting points, not rules):**
| App category | Typical pain moment | Persona | Formats that fit | Careful with |
|---|---|---|---|---|
| Sleep, meditation, calm | night in bed, racing thoughts | Mirror, tired, quiet voice | storytime, ASMR, selfie in bed | health claims; no "cures insomnia" |
| Fitness, steps, workouts | skipped workout, no time, gym nerves | Mirror or friend a step ahead | walk and talk, mirror, routine, first try | no body before/after; no promised weight loss |
| Budgeting, banking, saving | end of month, a bill, the banking app closed again | Mirror, converted skeptic | car, honest review, storytime | no invented amounts or returns; finance rules |
| Language learning | a trip, a waiter, a work call | Mirror, traveller | walk and talk abroad, skit, street interview | no fluency promises in days |
| Dating, social | a bad date, ghosting, small talk | friends, two people | skit, podcast, interview | no real people or fake matches |
| Productivity, planning | chaos, missed deadline, 47 tabs | Mirror, busy parent, student | desk tripod, routine, hidden cam | no invented time saved |
| Photo, video, AI tools | an edit that took hours, a bad photo | creator-type friend | first try, reaction, tutorial | the output shown only from real results |
| Utilities (cleaner, VPN, caller ID, scanner) | a full phone, a spam call, a moment of risk | Mirror, parent | reaction, honest review, car | no fear-mongering, no fake alerts or system UI |
| Kids, family, education | homework fight, screen time, bedtime | parent | storytime, couch tripod, dialogue | no claims about children's results; no minors as the speaker |
| Health tracking, period, nutrition | an unclear symptom, a doctor visit, meal chaos | Mirror | storytime, routine | health claims only from the Brand Kit; no diagnosis talk |
---
## Step 1 additions: audience, pain and persona first
1. **Brand Kit and pain map.** Find and read the Brand Kit (base Reference I). Build the **pain map** exactly as in `lyra-video-hooks` Step 1 (audience, pains in their words, desires, objections, product truth). If a hook round already made one for this app, reuse it. Pains missing or vague → 3 to 5 pain hypotheses in the audience's words, ask to confirm, and keep moving in the same message.
**What UGC takes from the Brand Kit:**
| Brand Kit field | Used for in UGC |
|---|---|
| Audience, segments, their daily life | the persona (archetype, age, look, market), the pain moment, the place |
| Pains, problems, customer words, reviews | the hook line, the speech, the "old way" beat |
| Desires, outcomes | the result beat, the identity trigger |
| Objections | the converted skeptic, honest review, objection-first spines |
| Product, features, value proposition | the one feature, the discovery and demonstration beats |
| Approved claims, proof, numbers | the only claims and proof the person may say or a caption may show |
| Offer, CTA | the soft CTA and its caption |
| Tone of voice | how the persona talks (word choice, humour, energy) and the voice anchor |
| Positioning (mass, premium, wellness, playful) | the polish level: raw, elevated or stylized UGC |
| Brand colors | subtle accents only (a mug, a hoodie, the room's light); UGC never looks branded |
| Markets, languages | the persona's market, the spoken language and accent |
| Must include / must exclude, forbidden claims | hard rules for every prompt and line |
| Assets (logo, screenshots) | logo on the end card; screenshots for the phone image and UI insert |
2. **The pain moment.** For the pain you lead with, write one line: who, where, when, what they do, what they feel. Example: "Student, 21, in bed at 2 am, scrolling, can't switch off, annoyed at herself." This line picks the place and the format.
3. **Customer words.** Store page, reviews, comments, support messages (hooks skill Step 1a). Short phrases only. They feed the speech, never as a copied review.
4. **Intake quiz** (base Step 1: one message, multiple choice, options from the Brand Kit, the recommended option first, 4–8 questions; skip what the task or the kit already answers), with these questions plus the base quiz questions that apply:
- Which pain or segment to lead with (offer your recommendation).
- Format, or "you decide" (default: you decide from the pain moment, see the format library).
- Persona preferences: age, gender, look, market; one persona or two for an A/B test.
- Language and market (the person speaks this language natively in the clip).
- Screenshots, if the app should be seen (screenshots only, never a screen recording).
- The store link (to match the ad promise and read the reviews), if not in the Brand Kit.
- Approved and forbidden claims, mandatory disclaimers or phrases, if the Brand Kit doesn't say (health, finance, kids apps above all).
- Raw or elevated look, if the Brand Kit's positioning isn't clear.
- Is AI-generated content allowed for this brand, and does the client have a disclosure rule.
- How many videos (default 1 concept; 2 personas if they want a test).
**Defaults (state, don't ask):** cold traffic · Reels / TikTok · 9:16 · **15 s** (10 to 30) · English · one persona · native speech in the clip (no separate voiceover) · no music for talking head formats, light instrumental music for vlog and POV (always its own node in the Video Editor, never inside the clip) · captions: ask the user in the approval message (if yes: all speech, added in the Video Editor; size 80, at 75% of the height, under the face: `lyra-video-editor` → Captions) · phone screen hidden unless there are screenshots · Seedance 2.5, 720p (1080p on the user's choice), sound on, duration adaptive · Nano Banana Pro for every image, 9:16, 2K (4K for close-up selfies), character count 2 · CTA spoken + caption, logo end card optional.
**Recommended first run:** A. Character images (the person decides the whole video; images are cheap).
## Step 2 addition: the UGC concept
The concept the user approves (base Step 2) has, per video: **pain moment** (one line) · **persona** (character card, or 2 to 3 persona options to pick from) · **place** · **camera setup** (handheld selfie, walk and talk, car, propped, tripod, mirror, someone else films) · **format** (and the template, if one fits) · **hook** (3 to 5 options from `lyra-video-hooks` with one recommended, or "no hook skill: why") · **spine** with the spoken lines and word count · **clip plan** (one clip or several, B-roll, UI insert) · **music** yes/no.
> C1 · storytime · Mia, 21, student (Mirror) · bed at 2 am, phone light · handheld selfie lying on her side · hook H3 (combined): the phone slips and taps her nose, she winces, says "Two a.m. and my brain won't shut up." · spine: pain → tea, podcasts, counting sheep → Calmly five-minute wind-down → out before it ended → free, try tonight · 35 words, one clip ~15 s adaptive, one jump cut · no music, room tone · screen hidden (no screenshots yet).
**Persona options.** When the audience is broad or the user has no preference, write 2 to 3 short character cards (different archetype, age or look) and recommend one; the picked one, or two for an A/B, go into the build.
---
## Person: casting from the audience
**Who talks.** Pick the archetype from the audience and the pain, then make it specific:
| Archetype | The viewer thinks | Works best for |
|---|---|---|
| **Mirror** (default for cold traffic) | "that's me" | most apps; same age, life stage, situation, problem |
| **Friend who figured it out** | "she's like me, a few steps ahead" | habits, productivity, money, learning |
| **Converted skeptic** | "she doubted it too" | categories with trust issues, objection-led ads |
| **Insider** (works in the field, no claimed credentials) | "she knows how this works" | finance, learning, career; never a fake doctor, lawyer or advisor, no white coat or titles |
| **Two people** (friends, couple, coworkers, interviewer + stranger) | "that's a real conversation" | skits, street interview, social and dating apps |
| **Parent / partner / roommate** | "that's my house" | family, home, health habits, shared money |
**Character card.** Write it once, in the script text node, and repeat it word for word in every image and video prompt (it is the character anchor, base Reference E):
> Character: Mia · 21 · student · light brown skin, freckles, dark curly hair in a loose bun, a few strands falling · no makeup, slight dark circles · oversized grey hoodie, thin silver hoop earrings · energy: tired, dry humour, speaks quietly · voice: young woman, early 20s, soft American accent, slightly husky, relaxed pace, a little sleepy
**Realism rules for the person:**
- Real, not pretty: natural skin texture, visible pores, small asymmetries, real hair, everyday clothes from the audience's life. Attractive is fine; model-perfect reads as an ad.
- Age, look and style match the segment and the market (a Lisbon student, a Texas mom, a Tokyo office worker look and dress differently). Diverse casting across variants, never stereotypes.
- Expression fits the moment of the pain (tired, annoyed, embarrassed, relieved), not a constant smile.
- One person in focus; a second person only in two-person formats.
- Never a real person, celebrity, known creator or a lookalike; never a real creator's voice; no third-party brand clothing logos.
- An AI person is never presented as a real customer, a verified user or a real review. First-person stories are creative scenes.
**Images: Nano Banana Pro, high quality, phone-real.** Every UGC person, keyframe and moment image is made with **Nano Banana Pro** (`google/nano-banana-pro`), the finals model of the base skill (Reference A): it holds faces, skin, hands and real rooms best. Nano Banana 2 only for quick drafts, then the winner is rerun on Pro.
- **Settings:** aspect ratio **9:16** (the video's ratio, base Reference E) · resolution **2K** by default, **4K** for close-up selfies where skin and eyes fill the frame · count **2** for the character image (the user picks one), 1 for the rest. Read the values from `list_node_configs`.
- **High quality is not polish.** High resolution is there so the details survive into the video: visible pores, fine hair, fabric texture, the small objects of the room. The look stays phone-real (natural light, deep focus, no beauty filter, no editorial styling). Seedance 2.5 copies what the reference shows, so a plastic or blurry image becomes a plastic or blurry video.
- **Skin:** "natural skin texture, visible pores, fine lines, subtle redness, slight unevenness, a few blemishes, no makeup airbrushing, no beauty filter", sized to the persona (a tired student, a busy mom). Never "flawless", "perfect", "porcelain", "glowing".
- **Setting:** the real place of the pain moment with 2 to 3 lived-in details, motivated light, sharp readable background (see Place). Never an empty, minimalist or showroom room.
- **Check before any video** (stage 1 gate): does the skin look like a real person filmed on a phone, and does the room look lived in? If not, rerun the image (cheap) with a stronger realism line; never spend video credits on a plastic image.
**Two personas for an A/B test.** One script, two character cards (different age, look or archetype), same place, same speech; two character images, two clips, two videos. The persona is the hypothesis ("students trust a peer more than an older sister type").
---
## Place: where the pain happens
The setting is the pain moment from Step 1, not a nice location. The viewer should recognise their own room, car or desk.
- **Lived-in, specific:** 2 to 3 concrete details that tell the story (a half-drunk energy drink and a charger cable on the duvet; parking ticket on the dashboard; a sticky note wall). Not a showroom, not piles of decor.
- **Motivated light:** the light that is really there (phone light at night, window light in the morning, car daylight, office fluorescent, bathroom mirror light). No studio light, no ring light catchlight unless the format is a podcast.
- **Time of day matches the pain** (night for sleep, morning rush for habits, end of month for money).
- **Sound of the place:** room tone, traffic, fridge hum, street noise; Seedance makes it with sound on. It sells the realism.
- **The phone is the camera.** Every UGC prompt says who holds the phone and how (see "Camera setups" below). Framing for speech: medium close-up, face and mouth clearly visible, eye level or slightly above, subject in the central 65% of 9:16.
- **Phone optics, not cinema optics:** wide phone lens ("shot on a 24mm smartphone front camera"), **deep depth of field with a sharp, readable background** (portrait blur and creamy bokeh read as a camera, not a phone), small handheld micro-jitters and drift instead of gimbal moves, a little autoexposure shift when the light changes, a little noise in low light, no heavy grading.
- **Variety without losing the person:** the same face can appear in several UGC spots (selfie in bed, on the couch, in the car) for different videos; keep the character card and change only the place.
- **One place per video by default.** A second place only when the story needs it (problem at night → result in the morning), with the same person anchor.
---
## Camera setups: how the person films themselves
In real UGC the person films themselves: the phone is in their hand, or they put it down somewhere and talk to it. This is what makes a video read as a post, not an ad. Pick one setup per clip, write it into the image and the video prompt, and keep it through the clip.
| Setup | What it looks like | Feels like | Best for | Prompt cues | Watch out |
|---|---|---|---|---|---|
| **Handheld selfie, spontaneous** (a strong default) | phone in one hand at arm's length, front camera, slightly above eye level; she grabbed the phone because she had to tell you something right now | urgent, honest, "I need to tell you this" | pain callouts, confessions, "wait, why did no one tell me", reactions | "she holds the phone in one hand at arm's length and films herself with the front camera, handheld micro-jitters, the frame drifts a little as she talks, her arm and shoulder edge visible at the side" | the free hand does one simple gesture at most; the arm doesn't change length mid-clip |
| **Walk and talk** (very native) | handheld selfie while walking: street, park, office corridor, supermarket, campus; the background passes behind her | on the go, real life, a thought she had on the way | routines, commute, productivity, money, "on my way to…" moments | "she walks toward camera while filming herself, the phone bobbing slightly with each step, the street passing behind her, natural walking rhythm" | steady pace, one direction, no crowds crossing in front; one short sentence per beat |
| **Car** | phone in a dashboard or vent mount, or in her hand while **parked**; driver's seat, seatbelt, window light | "talking to you in my car", private, casual | commute pains, busy people, parents, money and planning apps | "phone in a dashboard mount facing her" or "parked, she holds the phone and films herself from the driver's seat, daylight through the side window" | never a phone held in hand while driving (unsafe and it reads badly); moving car = phone in a mount |
| **Propped phone** | she set the phone down herself and leaned it on something: a shelf, a stack of books, a cup, the kitchen counter, the bathroom sink; static frame, she steps or sits back into it | settled, honest, "let me explain" | storytime, honest review, routines, GRWM, cooking | "the phone is propped against a mug on the kitchen counter, static frame slightly below eye level, she leans in and talks to it, a bit off-center" | a static frame needs life in the person: small moves, leaning in, looking away and back |
| **Tripod / clamp by the bed, desk, floor** | phone on a small tripod or a clamp, she sits on the bed, the floor, at the desk; wider frame, more of the room | longer talk, "sit down, story time", a creator setup | storytime, tutorials, day in my life, podcast-lite | "filmed on a phone on a small tripod at the foot of the bed, static wide-ish frame, she sits cross-legged on the bed facing it" | wider frame = smaller face; keep the mouth readable (medium shot, not full body) for speech |
| **Mirror selfie** | she films her reflection, phone in hand in front of her chest or face; bedroom mirror, bathroom, gym, elevator | outfit, body, routine, "look at this" | GRWM, fitness, fashion, beauty, routines; short lines or no speech | "mirror selfie: she holds the phone in front of her chest, the phone's back visible in the reflection, we see her and the room in the mirror" | the phone must not cover the mouth when she talks; mirror logic (reversed text, a second reflection) breaks easily; keep the background simple; better for short lines or a visual hook than a long monologue |
| **Set-up moment** (an opening beat) | the clip starts as she places or props the phone, adjusts it, sits back and starts talking | real, "I'm just recording this quickly" | the first beat of a propped or tripod clip; a combined hook | "the video opens as she leans the phone against the books, adjusts it once, sits back and starts talking" | keep it under 1 s, then speech; it is the visual beat, not a scene |
| **Someone else films** | a friend, a partner, an interviewer, a hidden camera; she is filmed, not filming | social proof of a moment, "caught on camera" | skits, street interview, hidden cam, couples | "filmed handheld by a friend standing in front of her, the friend asks from behind the camera…" | the filmer is off-camera with their own voice (see Voice) |
**How to choose.** The setup follows the pain moment and the energy of the speech: a sudden thought → handheld selfie; a thought on the go → walk and talk or car; a calm story or review → propped phone or tripod; something to show on the body or the outfit → mirror; a social moment → someone else films. Different setups for different videos of the same persona are a cheap way to make variety (same face, same voice, a new setup and place).
**Rules for every setup:**
- Write the setup in the image prompt too, so the character image already shows it (arm at the edge of the frame, the angle from the mug, the mirror).
- The camera moves only as the setup allows: handheld = small jitters and drift, walking = a gentle bob, propped and tripod = static (the person moves, the camera doesn't), car mount = small road vibration.
- The phone screen faces her, not us, unless there is a real screenshot (base Reference D).
- One setup per clip. A change of setup is a cut, written as a new shot ("cut to: she has propped the phone on the shelf…").
---
## Voice: how the person sounds
Default: **native speech in Seedance 2.5.** The spoken lines go in the video prompt in quotes, the model makes the voice and the lip-sync together. No separate voiceover node.
- **Voice anchor.** Describe the voice once in the character card and repeat it word for word in every clip: gender, age, accent, pace, energy, texture ("young woman, early 20s, soft American accent, slightly husky, relaxed pace, a little sleepy"). It must fit the face, the age and the moment.
- **Language and accent explicit** for every market ("speaks in natural European Portuguese, Lisbon accent"). One language per clip. For another market: new clip with the line written in that language (and a persona from that market if the user wants), not dubbing.
- **Delivery through words and action, not adjectives:** a pause written as a comma or an ellipsis, a breath before the key line, a half laugh, looking away then back. Never stage directions in the quoted line.
- **Lines Lyra's own producers put in UGC video prompts** (keep them, they fix common failures): "She starts speaking from the very first second of the video." · "She speaks calmly with natural pauses between sentences. No rushed speech." · "No voiceover narration, no off-screen voice, no dubbed audio. Only her live in-camera speech is heard." (drop the middle part when the format has an off-camera voice, like an interviewer or the person filming) · roughly **three short sentences per 10 s**.
- **Off-camera voice.** Interview, hidden cam and "friend filming" formats have a second voice behind the phone. Give it its own short voice description and tie its line to it ("the person filming asks from behind the camera: '…'"); the on-screen person answers.
- **Same voice across clips.** Native voices can drift between clips. Prevent: one longer clip instead of several where possible (Seedance 2.5 goes to 30 s), same voice anchor, same model. If it drifts anyway, offer: regenerate the weaker clip, merge into one clip, or switch to an ElevenLabs voiceover as audio reference (base Reference C; the video is fitted to the track).
- **Fallback when exact wording or a fixed brand voice matters** (or the user brings a recording): ElevenLabs VO, then the voiceover as audio reference in Seedance 2.5. Say once what changes: steady voice and exact words, a little less natural acting.
---
## Speech: what the person says
Write the speech from the pain map and the customer's words. It goes into a user text node "UGC script" (base Part 2), with the lines per clip.
**Default spine (problem first), 15 s:**
| Beat | Time | What the person does | Example (fictional app Calmly) |
|---|---|---|---|
| **Hook: the pain** | 0 to 3 s | names the pain in the audience's words, already mid-thought; built with `lyra-video-hooks` (see Hooks in UGC) | "Two a.m. and my brain won't shut up." |
| **The old way** | 3 to 6 s | what they tried, why it failed, a feeling the viewer knows | "Tea, podcasts, counting sheep… nothing." |
| **Discovery** | 6 to 10 s | how they found the app, the one feature, what it does for them | "Then I found Calmly. Five minutes, lights off, timer on." |
| **Result** | 10 to 13 s | a specific, believable change | "I was out before it ended." |
| **Soft CTA** | 13 to 15 s | casual, like a tip to a friend; offer from the Brand Kit | "It's free. Try it tonight." |
(35 words: fits 15 s at a calm pace, ending about 1 s early.)
**30 s app ad spine** (when the user wants 30 s, or the feature needs showing): hook (0 to 3 s) → pain and context (3 to 8 s) → discovery, the app named (8 to 12 s) → **demonstration**: one feature, one phone moment or real screen (12 to 18 s) → **benefit**, the specific reason it helps (18 to 23 s) → **payoff**, the result in life on the person (23 to 27 s) → CTA (27 to 30 s). About 70 words; usually one Seedance 2.5 clip of up to 30 s plus a UI insert.
Other spines when they fit better (say why in the plan): **first try** (she opens the app for the first time on camera and reacts honestly; the app version of unboxing) · **old way vs app** (a comparison: what she used to do vs what she does now) · **app first** (the person names or shows the app by second 2 to 3, then the pain it solved; a good A/B against problem first, often more clicks for utility apps) · **honest review** (what I expected, one small real drawback, why I still keep it; strong for warm traffic and skeptical audiences) · **storytime** (a short story with a turn, the app is the turn) · **objection first** ("I thought budgeting apps were pointless") · **tutorial / how I do it** (method first, the app named later; often higher intent) · **day in my life** (the app appears naturally in the routine) · **interview** (question → answer with the pain → the app) · **skit** (one person has the pain, the other has the fix).
**Speech rules:**
- **First person, spoken, simple.** Contractions, short sentences, everyday words, about a 5th grade reading level. Read it aloud: if it sounds like an ad, rewrite.
- **Start on the pain or the key word.** No "So", "Okay", "Hey guys". **When the app is named is a choice of the concept, not a rule:** problem first by default; app first (the app in the first seconds) when the hook is the app itself, the audience already knows the category, the user asks for it, or it is the A/B test. Say in the plan which one and why.
- **One idea per sentence, one short sentence per 3 to 5 s of clip.** Long, multi-clause lines break lip-sync.
- **Word budget:** about 2.5 words per second for a calm talker, 3.0 for energetic, 2.0 for slow and emotional, and the speech ends about 1 s before the clip ends. 15 s ≈ 30 to 35 words. Count them.
- **Numbers and abbreviations as spoken** ("two a.m.", "fifty euros"); spell the app name as it's pronounced if it's unusual, and check it in the result.
- **Natural imperfections, sparingly:** one pause, one self-correction or half laugh per video. Not a stack of "um".
- **Claims only from the Brand Kit or the user.** No invented numbers, durations of use, ratings or results. "Three nights in a row" only if it's a plausible creative scene, never as proof; no health, money or body results the app can't stand behind; no body before/after for health apps.
- **The CTA is soft and concrete:** the real offer ("it's free for seven days"), said like a tip. Same words as the CTA caption.
- **Echo, don't contradict:** captions and on-screen text repeat the spoken words.
**Checks for every script:** tied to one pain from the pain map · sounds like this persona, not a copywriter · specific to this app and moment (if it could sell a hundred apps, rewrite) · true · counted and fits the clip minus 1 s · the hook works muted with its caption.
---
## Hooks in UGC (use `lyra-video-hooks` often)
The hook beat of the spine (0 to 3 s) is where UGC ads win or lose. A selfie of someone starting to talk is the most common opening in the feed, so it needs a reason to stop: a sharper pain line, a physical beat, an unusual first frame. That is what the hook skill is for. **Read `lyra-video-hooks` and use it for the opening in most UGC ads.** It is a strong default, not a rule.
**Use the hook skill when** (most cases):
- cold traffic, or the user didn't say;
- the video is for a test (almost every paid ad);
- the format opens on a person just talking (selfie, honest review, car vlog, podcast): it needs a visual beat or a sharper line;
- the user asks for variants, a stronger start, or the hook rate is low;
- a UGC winner is fatiguing: keep the body, new hooks (hook multiplier, mode A of the hook skill).
**Skip it, or keep it light, when:**
- the user gives their own opening line or first scene (use it as is, check it against the hook skill's line checks once);
- the format's calm opening is the concept (ASMR, storytime whisper, calm contrast) and a hard interrupt would break it;
- a Lyra template already has its hook built in (Fridge Camera, Blinds, Hook door, Balcony, Trunk POV): adapt that hook, don't add a second one;
- warm retargeting where the offer opens the ad;
- one quick video for a look, not a test.
Say in the plan which way you went and why, in one line.
**How the two skills work together:**
1. **One pain map.** Build it once (hook skill Step 1) and use it for both the hook and the speech.
2. **Hook options in the concept.** For one UGC video, write 3 to 5 hook options from the hook base (not the full bank of 12 to 15) in the concept step, each one line with its kind and the persona's spoken line; recommend one. For a test, or when the user asks, write the full hook bank and build N hooks on one UGC body (hook skill, mode A or B).
3. **Hook kinds that fit UGC best:** **combined** (a small physical beat at frame 0, then the persona says the pain line: a clap, a phone flipped toward the lens, a sigh into the pillow, a door opened) · **verbal** (pain callout, POV, confession, storytime cold open, objection first, mistake, "people talking about the prospect") · **format hooks** (comment reply, hidden cam, street interview question, object POV) · **visual** only when the pain can be seen at once. The awareness table of the hook skill picks the kind for the audience.
4. **Same person, same voice, same place.** The hook is played by the UGC persona with the same character card and voice anchor, so the hook and the body cut together. A hook in a different spot (fridge, trunk, balcony) still uses the same persona reference; the body follows right after.
5. **Where the hook lives in the graph.** Spoken or combined hook in the same place → the first beat of the main clip (the opening action and the line first in the prompt; "starts speaking from the very first second"). Visual or format hook in another spot, or N hooks for a test → its own 4 to 5 s clip, trimmed to 1.5 to 3 s, cut into the shared body in the Video Editor (hook skill: cut point, end state).
6. **The speech continues the hook.** The second line answers or deepens the hook, never repeats it; if the hook opens a loop or promises something, the body pays it off.
7. **Caption on frame 1.** 2 to 6 words echoing the hook line, marked for post (hook skill rules).
**Hook naming:** add the hook code to the final's name: `B2-A:CantSwitchOff-F:UGC-Storytime-P1-C1H3`.
---
## Format library
A reference, not a menu. Pick from the pain moment; combine and adapt.
| Format | What it looks like | Pick it when | Lyra templates |
|---|---|---|---|
| **Selfie talking head** | front camera, arm's length, talking like on FaceTime with a friend | the pain is a feeling or a thought; the default | Talking head with phone, Mini Girl on Phone (stylized) |
| **Vlog in motion** | walk and talk selfie, car (phone in a mount, or in hand while parked), skating, commuting (see Camera setups) | the pain lives in a routine or on the go | Car Vlog, Skateboarding App Discovery Vlog, Female Street Promotion |
| **Storytime / confession** | lying in bed, on the couch, on the floor; quiet, honest, personal | the pain is private or a bit embarrassing (sleep, money, loneliness, habits) | Life Transformation, Sofa |
| **GRWM / routine** | getting ready, cooking, tidying, talking over the shoulder | the app fits a daily routine (habits, wellness, planning) | none (build from scratch) |
| **Day in my life POV** | short handheld moments of a day, the app in one natural moment | lowest ad feel; the app is part of life | none (build from scratch) |
| **Honest review / reaction** | sitting at a desk or in the car, "ok, real review", one small drawback | skeptical audience, warm traffic, competitive category | none (build from scratch) |
| **Street interview** | handheld, a mic in frame, a quick question, a stranger answers with the pain and the app | broad consumer apps; recognisable question | Interview, Interview POV |
| **Skit / dialogue** | two people: a friend catches the other, a coworker asks "what are you doing?" | social, dating, productivity, shared pain | Hidden Cam, Stream, Podcast App Discovery |
| **Podcast / insider clip** | two mics or one host, studio-ish room, a confident opinion | trust-heavy apps (finance, learning, career) | Podcast, App Presentation |
| **First try / first open** | "ok, I just downloaded this, let's see", first session on camera, honest reaction | new or surprising apps, AI tools, games-like apps; the app version of unboxing | none (build from scratch) |
| **Old way vs app** | she shows how she used to do it (notes, ten alarms, spreadsheets), then how she does it now | utilities, productivity, finance, learning | none (build from scratch) |
| **VO over UGC moments** | silent handheld moments of her day, her own voice telling the story over them | when lip-sync is hard (walking fast, mirror) or for a calm diary feel | none (VO as audio reference or composed in the Video Editor) |
| **ASMR / whisper** | close mic, soft voice, calm room | calm, sleep, meditation, self-care apps | ASMR, Microphone UGC |
| **Hook-led UGC** | object POV, door, blinds, balcony, fridge, trunk, then the person talks | the first second needs a visual stop | Fridge Camera, Trunk POV, Blinds, Hook door, Balcony (see lyra-video-hooks) |
**Pain → format, in short:** a feeling → selfie or storytime · a moment in the day → vlog, routine or POV in that place · a doubt → honest review or objection first · a social pain → skit or interview · a trust problem → insider or podcast · a calm category → ASMR.
**Lyra UGC templates.** `list_templates` with tags ["UGC", "Talking Head"]; offer up to 3 that fit (title + one line why + preview link); always re-check the list. Picked → `get_template`, `use_template`, then adapt as in `lyra-video-hooks` Step 1b, plus for UGC:
- The video model becomes **Seedance 2.5**, references only, 720p by default (1080p on the user's choice), sound on (several templates use Kling 3.0 or Seedance 2.0 at other settings); say it once and follow the user's choice.
- Rewrite the script node with this skill's speech (problem first, the persona's words), replace every "[App Name]" and "[main benefit]".
- Replace the template's persona with a character card from the audience; remove "flawless skin", "Vogue editorial", "4K" style tags (UGC is phone-real).
- Remove on-screen text, stickers and "link in bio" from prompts; captions go in the Video Editor.
- The image and character nodes keep their prompts' idea; switch to Nano Banana Pro for finals unless the user wants the template's model.
---
## Best way to build it
The user's explicit choices override any row. Models and prices: base Reference A.
| If the video is | Best approach (graph) | Models |
|---|---|---|
| **One person, one place, ≤15 s** (default) | UGC script (text) → character image in the setting (count 2, user picks) → **one clip**, adaptive duration, the speech in quotes, 1 to 2 jump cuts written as "cut to" inside the clip → Video Editor (captions, optional end card) | nano-banana-pro · seedance-2.5 |
| One person, 15 to 30 s | as default, one clip up to 30 s adaptive; or 2 clips cut on a natural pause, same references, same voice anchor | seedance-2.5 |
| Two places or several moments (problem → result, day in my life) | character image → one image per moment made **from the character image** ("Change the setup and her pose: she is now… Keep the same woman, face, hair") with the character as input, so identity carries over → one clip per moment, or one multi-shot clip with all moment images as references ([Image1] scene 1, [Image2] scene 2…) → Video Editor | nano-banana-pro · seedance-2.5 |
| Hidden cam, interview, friend filming | character image (the person on screen; the filmer stays off-camera) → clip with the off-camera question and the on-screen answer, each tied to its voice | nano-banana-pro · seedance-2.5 |
| The user already has an app packshot or app video | as default; their file appended in the Video Editor as the last 2 to 4 s (don't ask for a screen recording; use it only if they bring one) | video_composer |
| Shows the app | as default + phone image (character holds the phone, the user's screenshot) → short UI insert clip laid over in the Video Editor, or the phone image as a reference in the main clip (base Reference D) | nano-banana-pro · seedance-2.5 (UI insert: seedance-2.0, frame) |
| B-roll moments (hands, the pain object, the room) | 1 to 2 short clips (4 to 5 s, trimmed to 1 to 2 s) from keyframes with the same anchors, cut over the talking head in the Video Editor while the voice continues | seedance-2.5 |
| Two people (skit, interview, couple) | two character images → one shared keyframe of both in the place → clip with each line tied to its speaker by [ImageN] and the other person still; if the wrong person talks, one clip per line joined in the Video Editor | nano-banana-pro · seedance-2.5 |
| Two personas for A/B | one script → two character images → two clips → two Video Editors, everything else identical | nano-banana-pro · seedance-2.5 |
| Several openings on one body | build the body here, hooks from `lyra-video-hooks` (mode A) | as the hooks skill |
| Another language or market | same structure; the speech rewritten in that language (not translated word by word), the voice anchor with that accent; new clip | seedance-2.5 |
| Exact words or a fixed voice needed, or the user's own recording | VO (ElevenLabs, or the user's file uploaded) → audio reference in the Seedance 2.5 clip | elevenlabs/v3 · seedance-2.5 |
| Lyra UGC template picked | use_template → adapt (Format library) → upgraded settings | as the template, upgraded |
| Many personas or formats, tight budget | character images for all, clips only for the 1 to 2 the user picks | seedance-2.5 |
**Clip plan.** UGC lives on jump cuts: they hide small drift, keep the rhythm and look native. Write them in the script (where the cut is, what changes: framing slightly closer, a new sentence). A new stimulus every 2 to 4 s (a cut, a B-roll, a gesture). Seedance's minimum is 4 s: short beats are trimmed in the Video Editor.
**Music.** **Never inside the clip:** every UGC clip prompt says "Only her live in-camera speech and the room's natural sounds; no music, no background music, no soundtrack, no score", because music baked under the live voice can't be removed (base Reference C). Talking head, storytime, honest review, ASMR: usually no music at all, the room tone carries it. Vlog, POV, routine: light instrumental (lo-fi, soft pop beat), barely under the live voice (Lyra's UGC templates sit at about 0.05 to 0.1 track volume under in-camera speech; up to about 0.25 only under a clean studio voiceover), length = video + ~5 s, instrumental only (base Reference C).
**Video Editor.** One `video_composer` per final: hook clip (if separate) → main clip(s) → B-roll and UI inserts on a layer above → optional packshot or end card (logo, 1 to 1.5 s, or none: many UGC ads end on the person). Captions only if the user said yes (asked in the approval message): all speech, word by word, in one place, by the base rule (`lyra-video-editor` → Captions): size 80, at 75% of the height (y = 1440 on 1080×1920), never over the face. The editor makes them from the speech (caption track): set the size and position yourself once the track exists; the user checks the words and the app name; tell the user what to check. Keep the clip's own sound (it is the voice); mute only clashing B-roll sound.
**Layout.** Section "Script" (UGC script, character card), Section per persona (character image, keyframes, clips), Section "Final" (Video Editor). Labels: "Character: Mia", "Mia: bed 2 am (clip)", "B-roll: phone on duvet", "Final: P1 Mia · storytime sleep".
## Run options for UGC
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes, per option. **A. Character images (recommended):** every persona image (count 2) and keyframes · **B. Clips** for the persona the user picked · **C. Everything** → the Video Editor. When a character image has several results, the user selects one in Lyra before the clips (references pin to the selected result).
---
## Prompt rules (UGC)
| Node | Write | Avoid |
|---|---|---|
| UGC script (text node) | character card (with voice anchor), pain moment, place, format, spine with the lines per clip, word count per clip, cuts, B-roll, captions marked for post, CTA | ad copy; claims not in the Brand Kit |
| Character image | "UGC phone photo" → the character card word for word → in the place, mid-moment (the expression of the pain) → phone framing ("shot on a 24mm smartphone front camera", selfie at arm's length, off-center, candid) → motivated light → deep depth of field, sharp background → 2 to 3 lived-in details → "natural skin texture, visible pores, subtle asymmetry, flyaway hair, no beauty filter, no makeup airbrushing, casual, unpolished" → exclusions | "flawless", "perfect skin", "Vogue", "editorial", "luxury", "8K", "HDR", studio light, portrait bokeh, minimalist or empty background; text; logos; a visible phone screen without a screenshot |
| Keyframe (second place, two people) | the same card word for word, the new place, who is where, the moment it starts | re-inventing the person; different light logic |
| Video clip with speech | roles first ("[Image1] is Mia: face, hair, hoodie, her bedroom at night") → format and camera ("UGC selfie video, phone front camera at arm's length, handheld micro-jitters") → "starts speaking from the very first second" → action before each line → the lines in quotes, tied to the speaker → natural pauses, no rushed speech → voice anchor and language → "only her live in-camera speech" → cuts as "cut to" → room sound and action sounds, then "no music, no background music, no soundtrack, no score" → end state → short "Avoid" line | the full look re-described (the reference carries it; a short identity line is enough); stage directions inside quotes; more than one sentence per 3 to 5 s; on-screen text |
| Dialogue clip | each line after "[Image1] (Mia) says:" or "[Image2] (Leo) says:", the listener's reaction without speaking ("Leo listens, only Mia's mouth moves") | two people talking over each other; lines without a speaker |
| B-roll clip | one concrete action of hands or an object, same anchors, no speech, 4 to 5 s | faces (drift); a second person |
**Pattern: video clip with speech (Seedance 2.5, references).**
> [Image1] is Mia: her face, curly hair in a loose bun, grey hoodie, and her dark bedroom at night. UGC selfie video, shot on a 24mm phone front camera held at arm's length, handheld micro-jitters, deep focus, phone light on her face, warm lamp in the background. She starts speaking from the very first second. Mia lies on her side in bed, the phone slips and taps her nose, she winces, looks straight into the lens, tired but amused, and says: "Two a.m. and my brain won't shut up." She rolls onto her back, sighs, and says: "Tea, podcasts, counting sheep… nothing." Cut to: a little closer, she lifts the phone, and says: "Then I found Calmly. Five minutes, lights off, timer on." She smiles softly and says: "I was out before it ended. It's free. Try it tonight." Natural pauses between sentences, no rushed speech. Voice: young woman, early 20s, soft American accent, slightly husky, relaxed pace, a little sleepy. Only her live in-camera speech is heard, no voiceover. Quiet room tone, faint street noise, no music, no background music, no soundtrack, no score. Ends on her holding eye contact, a small smile. Avoid: background music, text, captions, beauty filter, studio lighting, identity drift, warped hands, visible phone screen.
(Hook H3 from the concept as the first beat: the phone tap is the physical interrupt, the line is the pain. 35 spoken words, about 14 s at a calm pace, in an adaptive clip that should land near 15 s; check the real length and trim only the silence after the last word. The app's real screen is shown, if at all, as a UI insert.)
**UGC prompt checklist** (what every image and video prompt specifies, when it matters for the shot): objective (app ad, which beat) · the app's role (hidden phone, phone moment, real screenshot) · person (the character card) · action (one clear action, the phone interaction) · setting (the pain moment, 2 to 3 details) · camera setup (who holds the phone, how it moves) · shot size and framing · light (motivated source) · texture (skin, fabric, room) · mood (the emotion at this beat) · format (9:16, duration in the node settings, not in prose) · constraints (what must not change, the artifacts to avoid).
## De-slop for UGC
Base Reference H, plus what breaks UGC in particular:
- **Too polished:** studio light, perfect teeth and skin, beauty filter, cinematic shallow depth of field, color grading, a camera that floats. UGC = phone camera: autoexposure, slight wobble, a little noise in low light, imperfect framing.
- **Overacting:** big hand gestures, constant smile, "excited" eyebrows, nodding on every word. Ask for small, real reactions: a look away, a pause, a half laugh.
- **Lip-sync slop:** mouth out of sync, the wrong person speaking, garbled app name. Prevent: face frontal or three-quarter, mouth visible, short lines, one speaker at a time.
- **Voice slop:** voice too old or too polished for the face, a radio announcer tone, voice changing between clips, rushing to fit the words.
- **Fake proof:** fake star ratings, fake comments on screen, "verified user", a doctor's coat.
- **App fidelity:** the phone looks the same in every shot (model, color, case); the screen matches the user's screenshot exactly or stays hidden; the app icon, logo and store badges are never generated (the uploaded logo goes on the end card); the thumb really presses the glass and the screen reacts in the right place.
---
## Truth and disclosure
- An AI person is a creative performance, never a real customer. No fake testimonials, reviews, ratings, "verified" badges or durations of use as proof. Real reviews can be quoted as proof only as text (caption, card), attributed as reviews, never put in an AI person's mouth as if they wrote it.
- No real people, creators, celebrities or lookalikes; no cloned voices of real people.
- No credentials the persona doesn't have (doctor, financial advisor, therapist); no health, money or body results beyond the Brand Kit's approved claims.
- Platforms label AI content: Meta and TikTok expect a visible AI label on photorealistic synthetic people, and auto-detect content credentials. In the US the FTC treats an undisclosed synthetic endorsement as a deceptive testimonial and expects both "ad" and "AI" disclosure. Tell the user once, in the final report, to turn on the AI-generated label when they set up the campaign. Not legal advice; they check current platform rules.
- **Brand safety** (Lyra's System Preamble, base Reference B): no profanity, no political statements, no unsubstantiated health claims, no competitor disparagement. The Brand Kit's **forbidden claims are enforced absolutely**, in every spoken line, caption, visual and VO; if the user asks for one, say once that it is on the kit's forbidden list and leave it out unless the user confirms the kit is outdated.
---
## Deliverable and naming
1. A "UGC script" text node: pain moment, character card, place, format, speech per clip, cuts, captions marked for post.
2. Character image(s), clip(s), B-roll and UI inserts as planned.
3. One finished video per persona (or per format), each in its own Video Editor.
Name every final with a code the media buyer can paste into Ads Manager: `B{batch}-A:{angle}-F:UGC-{format}-P{persona}-C{concept}H{hook}`, e.g. `B2-A:CantSwitchOff-F:UGC-Storytime-P1-C1H3` (drop `H` when no hook skill was used). Node label: "Final: P1 Mia · C1H3 storytime sleep".
---
## Common mistakes (UGC)
| Mistake | Prevention |
|---|---|
| Persona invented without reading the Brand Kit's audience | Pain map and pain moment first; casting from the audience |
| UGC opens on someone just starting to talk, no hook | Hook from `lyra-video-hooks` by default (Hooks in UGC) |
| Hook played by a different person or voice than the body | Same character card and voice anchor in the hook |
| Second line repeats the hook instead of moving on | The speech continues the hook |
| Portrait blur, gimbal moves, graded "cinematic" phone video | Phone optics: 24mm, deep focus, micro-jitters |
| Nobody holds the camera (a floating, smooth "film" camera) | A camera setup in every prompt: handheld, walking, car mount, propped, tripod, mirror, someone else films |
| Phone held in hand while driving | Phone in a mount, or the car is parked |
| Model-perfect person, studio light, editorial look | Realism rules; phone-real light and framing |
| Setting chosen because it looks nice, not where the pain happens | The pain moment picks the place |
| Speech written as ad copy | Spoken words, read aloud; the app named where the concept planned it |
| Fake testimonial ("I've used it for 3 months", 5 stars) | Creative scene only; proof only from real reviews, as text |
| Too many words, rushed voice, broken lip-sync | Word budget, one short sentence per 3 to 5 s, clip minus 1 s |
| Voice doesn't fit the face or changes between clips | Voice anchor word for word; one longer clip; fallback VO as audio reference |
| The wrong person speaks in a dialogue | Lines tied to [ImageN]; listener still; one clip per line if needed |
| Kling or Veo for UGC, sound off | Seedance 2.5, sound on (720p by default, 1080p on the user's choice) |
| First / last frame on Seedance 2.5 | References only |
| Invented app screen in the person's hand | Screen hidden, or the user's screenshot as UI insert |
| Captions added without asking, or forgotten after a yes | Ask in the approval message; if yes, captions for all speech in the Video Editor |
| Seedance adds its own background music under the live voice | No-music sound line in every clip + "background music" in Avoid; our music only in the Video Editor; rerun a clip that still has music |
| Music under a talking head drowning the voice | No music by default for talking formats; otherwise about 0.05 to 0.1 under live speech |
| Template run as it came (Kling, "flawless", text in prompts) | Adapt per Format library |
| Two personas differ in script or place too | Only the persona changes in an A/B |
| AI label not mentioned | One line in the final report |
## Quality gates (UGC)
- **Stage 0 (script, Claude checks before sending):** tied to one pain? Hook built with the hook skill (or a stated reason why not), and it passes its line checks? Persona, place, voice and speech tell one idea? Words counted, fit the clip minus 1 s? Spoken, simple, specific, true? No fake proof?
- **Stage 1 (character images):** looks like a real person from this audience, not a model? Phone-real, not editorial? Place matches the pain moment? Expression fits? Hands and phone natural, screen hidden or right?
- **Stage 2 (clips):** lip-sync matches the words? The app name pronounced right? Voice fits the face and stays the same across clips? Not rushed, natural pauses? Small real gestures, no overacting? Same face and outfit through the cuts? Camera feels like a phone, and it moves as the setup allows (handheld jitters, walking bob, static when propped)?
- **Stage 3 (final), app ad check:** is it clear in one watch what the app does for this person? Does the app fit the scene naturally, not glued on? Does the promise match the store page and the real first session? Is the CTA an install or trial step with the real offer?
- **Stage 3 (final):** pain recognisable in 1.5 to 3 s? Spine in order, CTA at the end, same words as the caption? Captions (if the user said yes) on all speech, size 80, at 75% of the height, not over the face? Music (if any) under the voice? 9:16, planned resolution (720p by default), planned length? Named with its code? AI label reminder given?
## After the test
Read the test as in `lyra-video-hooks` (After the test): hook rate, hold rate, then the numbers that matter for apps: installs per 1,000 impressions, cost per trial, trial to paid, day-7 retention. UGC formats differ downstream: skits and method-first videos often get fewer but better clicks, so judge by trials and payers, not CTR alone. The persona, the pain and the format are each a hypothesis: say which one won. Then offer: a new persona on the winning script, the winning persona in a new format, new hooks on the winner (`lyra-video-hooks`, mode A), other sizes or languages.
lyra-ui-motion-video44.8 KB
View saved version →
---
name: lyra-ui-motion-video
description: "App UI creatives in Lyra with every UI text kept exactly as in the user's screenshots - UI motion video ads (real app screens, buttons, cards, logo and icon in motion), store-style end cards with an install button, and App Store / Google Play screenshot sets with variants. Use for \"animate my app screens\", \"UI animation / motion design ad\", \"floating phone video\", \"show the app in the video\", \"end card with install button\", \"packshot like the App Store\", \"store screenshots\", \"screenshot set for Google Play\", or screenshots to bring to life. Core video rules come from lyra-video-ad-generation."
---
# lyra-ui-motion-video
Mini skill for everything where **the app's interface is on screen**: UI motion video ads, UI moments inside other videos, the store-style end card, and App Store / Google Play screenshot sets. Its one job above all: **the UI the viewer sees is the UI the user sent**, with every word, number, icon and color the same.
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**Our UI is almost always a mobile app.** Most Lyra users are mobile apps, so "UI" here means the app's own screens on a phone (iOS or Android), its icon, its logo and its store presence. Websites, dashboards and desktop software follow the same rules.
**This is a way of thinking, not a script.** The rules below are defaults and good practice; use judgment and say why in one line when you choose differently. Fixed: **UI fidelity** (the rules in the next section), truth (no features, numbers, ratings or badges the app doesn't have), the Brand Kit's facts, Lyra's technical limits, and the user's explicit choices.
**Base skill first.** Everything not written here follows `lyra-video-ad-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, prompt rules, models (Reference A), audio (C), app UI (D), consistency (E), prompt craft (F), errors (G), de-slop (H), Brand Kit (I), Meta app ads (J). This file adds what is specific to UI. If the two disagree, the user wins, then this file, then the base skill.
**Other skills point here for UI.** A hook that shows the app (`lyra-video-hooks`), a UGC creator with a phone moment (`lyra-ugc-video`), any base-skill ad with a screen: their UI moments follow this file's fidelity rules, model choice and checks. This skill itself owns videos where **the interface and the brand are the main character**, the end card, and store screenshot sets.
---
## UI fidelity rules (hard)
1. **Never invent or change anything in the UI.** No new screens, buttons, labels, numbers, icons, colors, fonts or layout; no "cleaning up", simplifying, translating or modernising the app. If it isn't in the user's screenshots, it isn't on screen.
2. **Every text that appears on a screen is identical to the user's screenshot**, letter for letter, number for number, including small labels, tab names, prices and dates. Maximum accuracy, every frame.
3. **Screenshots only** as the source (never ask for a screen recording). No screenshot for a moment → the screen faces away, is dark, or is blurred.
4. **No text generated into a video.** No subtitles, captions, headlines, stickers, price tags or overlays in a video prompt. Any text the ad needs (headline, caption, CTA, offer) is added **in the Video Editor** on top of the finished clips. The only text a video model may show is the UI text already inside the frame image it animates, and the prompt tells it to keep that text unchanged.
5. **Every image that combines the screenshot with something else** (the character holding the phone, a phone on a backdrop, an end card, a store screenshot) **is checked against the screenshot before any video is made from it**: every word, number and icon. A wrong letter in a frame becomes a wrong letter in the whole video.
6. **The more UI, the shorter and simpler the clip.** A lot of UI is split into several small clips (one screen or one state each), joined in the Video Editor.
7. **When in doubt, lay the real file on top.** Anything that must be read word for word and keeps failing in generation goes into the Video Editor as the original screenshot, logo or end card image.
## Screens: ask first, then work with what you get
**Always ask about the screens before planning a UI video**, in one message (with the other Step 1 questions):
- Which screens should be in the video, and how many? Please send a screenshot of each.
- In what order should they appear?
- What should happen on screen: **where to tap** (which button or element), what scrolls, what opens, what appears after the tap? For every action, a screenshot of the screen **after** it.
- Anything on the screens that must not be shown (personal data, unreleased features)?
**Work with exactly what the user gives. Never invent.**
- **One screenshot → one-screen video.** Build it on that screen alone: float, slow push-in, light sweep, button glow, card lift, the end card. A tap only as a press effect on the same screen; **no next screen, no new state, no new element** that isn't in the screenshot. Say once in the plan that more screenshots (with the after-state) would allow a tap-through demo; if the user says one screen is enough, do one screen, without pushing.
- **The user says "only one screen"** → one screen, done well.
- **Several screens** → help the user get the best result with all of them: order them as a story (the pain or the start → the action → the result), one clip per screen or state, a tap as the cause between two states (first + last frame), every frame checked.
- **An action without its after-screenshot** → ask for it; if there is none, show only the start state (the tap lands, nothing new appears) or cut away from the screen.
**Check the screenshot quality as soon as they arrive.** Look (when you can see them) or ask: is the resolution enough (ideally the short side about 1080 px or more), is it sharp, without heavy compression, cropped edges, personal data, notifications or a cluttered status bar?
- Not good enough → ask once: "Do you have sharper originals? A PNG export straight from the phone or from the design file (Figma) works best."
- No better ones → **improve the screenshot in Nano Banana Pro** before using it: an Image Generation node with the screenshot connected, same ratio, the highest resolution: "Upscale and sharpen this app screenshot. Keep it exactly as supplied: the same layout, every word, number, icon and color. Do not redesign, translate, add or remove anything; only remove blur, noise and compression artifacts." Then **check the improved version word by word against the original with the user**; it becomes the source only after that check. It never "fixes" content; anything unreadable in the original stays as it is or is asked for.
## Setting expectations: UI is hard for AI video
Say it once, in the plan, in plain words: **an app screen is one of the hardest things for AI video.** When the screen moves, small letters and numbers can drift or change for a moment. That's why the build is careful: clean sharp screenshots, checked frames, Seedance 2.0 frames for screen shots, small motion, short clips, and a check of every result. The aim is a **good result on the first or second run**; when a letter still drifts, only that piece is fixed (rerun with less motion, a Seedance 2.0 insert, or the exact screenshot laid on top), not the whole video. Never promise pixel-perfect UI in a moving shot; pixel-perfect is what layers in the Video Editor give.
## The fidelity ladder
Put every element on the lowest rung it can live on:
| Rung | How the element gets into the video | Exactness | Motion | Use for |
|---|---|---|---|---|
| **1. Layer** | the original file (screenshot, logo, icon, end card, text card) as an **image layer in the Video Editor** (position, size, duration) | pixel-perfect, no model touches it | none on the layer itself; motion comes from the clip under it and from the cut | logo, CTA, offer, store badges, headlines, any screen that must be read word for word |
| **2. Frame** | the screenshot or a checked design frame as **first frame**, and a second exact state as **last frame** if the screen changes, on **Seedance 2.0** | the picture is kept; small drift possible | small: glow, pulse, float, slow push-in, a tap, a short slide | **the default for UI**: hero screens, UI inserts, state changes, the end card coming alive |
| **3. Reference** | the screenshot or phone image as a **reference** on Seedance 2.5 (or 2.0) | layout kept, small text can drift | free | the phone moment inside a person-led video on Seedance 2.5 (checked; fixed with a 2.0 frame insert if needed); screens that are small or supporting |
| **4. Prompt only** | the model draws it from text | none | free | only abstract brand motion: gradients, light, shapes, particles in brand colors. **Never** UI, text or a logo |
**Rule of thumb:** the more readable text an element carries, the less it moves and the lower its rung.
## Which model for UI
**Two models, chosen by who leads the shot:**
- **The screen leads → Seedance 2.0.** Lyra's own model for UI/UX and moving text; it takes images as **frames** (kept exactly). Use it for UI motion, floating phones, cards, demos, UI inserts and the end card.
- **A person leads → Seedance 2.5.** When the video is mostly a realistic person (UGC, talking head, lifestyle, a scene with a lot of human action), the main clip is **Seedance 2.5** with references: the character image and the phone shot (character + screenshot). Seedance 2.5 is the best model for people and also handles a phone moment well.
**Person + UI: the two-step method.**
1. Make the person's clip on **Seedance 2.5** with the phone shot as a reference, and **check how the UI behaves** in it with the user: the screen identical to the screenshot through the whole moment (first, middle, last frame), no morphing text, the tap in the right place.
2. **If the UI breaks** (or the UI moment is long or important, so plan it from the start): make a **separate UI-only clip on Seedance 2.0** with the phone shot (or the screenshot) as **frame**, a few seconds of the screen with a finger tap or a small move, and lay it over that moment in the Video Editor (layer above the main clip, trimmed to the moment). The person's acting stays from 2.5, the exact UI comes from 2.0.
| Situation | Model | How images connect | Clip |
|---|---|---|---|
| **The screen leads** (UI motion, floating phone, cards, demo) | **Seedance 2.0** | **frames** (first, + last for a state change) | 4 to 6 s, one screen or one state |
| **A separate screen or UI insert** to lay over the main video in the Video Editor | **Seedance 2.0** | **frames, never references** | 3 to 5 s, trimmed to the moment |
| **A video mostly with a realistic person**, UI in it (UGC, talking head, lifestyle) | **Seedance 2.5** for the main clip | references only (character image + phone shot) | as the scene; **check the UI**; if it breaks, a separate **Seedance 2.0 UI-only clip with frames** laid over that moment |
| **A short phone moment where the screen matters more than the person** | **Seedance 2.0** | frames | 3 to 5 s, cut into the person's video |
| **A lot of UI** (several screens, many small texts, a flow) | **Seedance 2.0** | frames | **split**: one clip per screen or state, 4 to 6 s each, joined in the Video Editor |
| An exact change from state A to state B (tap, toggle, result appears) | **Seedance 2.0** (Kling 3.0 Pro as the alternative) | first frame = A, last frame = B | 4 to 5 s, one tap |
| The end card coming alive | **Seedance 2.0** | frame | 3 to 4 s |
| Brand motion background behind layered UI | Seedance 2.0 | prompt only (no text) | 8 to 10 s |
Never: an image as first/last frame on Seedance 2.5 (error) · frames and references mixed in one node · one long busy clip carrying the whole UI story · 1080p without the user choosing it (720p by default; Seedance 2.0 Fast and Mini can't do 1080p).
**How much UI is "a lot".** Split when a clip would show more than one screen, more than one state change, a scroll through a list, or small text the viewer is supposed to read. Keep it in one clip when the UI is a single screen glimpsed for 1 to 3 s inside a bigger scene.
---
## How to think about UI motion
**What it is.** A short ad where the app is shown as designed objects in motion: a phone with the real screen floating in a brand-colored space, screens sliding in as cards, a button pulsing, a finger tapping and the result appearing, the icon bouncing into the end card, a headline landing between screens. It sells by showing **what the app looks like and what it does**, cleanly and fast. It works for apps whose UI is attractive or whose result is visible on the screen (a plan, a chart, a scan, a finished edit, a balance).
**Motion that keeps text safe vs motion that breaks it:**
| Safe (default) | Risky (only with frames and a check, or as a layer) | Breaks text (avoid on anything with text) |
|---|---|---|
| locked camera · slow push-in or pull-out · gentle float or drift · fade · slide in from an edge and stop · small scale from center · light sweep or glow across the glass · soft shadow and depth · button pulse · small icon bounce · one finger tap · a card lifting a little off the screen · background motion behind the UI | A → B with first + last frame · a short scroll of a few rows · a card fanning out of a stack · the screen expanding to fill the frame · a toggle or check mark switching | rotation, flips, orbits around the phone · deep 3D perspective · heavy bounce or elastic stretch · one screen morphing into another without both states given · letter-by-letter typing · counting numbers · several text elements moving at once · long fast scrolls · whip pans across UI · the phone turning so the screen goes out of view and back |
**Principles:**
- **Real screens, not redrawn ones.** Real screens build trust and show what the viewer will actually get.
- **One product moment per video.** One key screen or one "aha" (the plan appears, the chart fills, the scan finds it), not a walkthrough. A second feature is a second video.
- **One primary movement + one supporting movement per shot.** Everything else is still, and the prompt says so.
- **Describe stillness as much as motion.** What isn't mentioned gets guessed: "the screen content and all text stay perfectly still and sharp" is as important as the motion line.
- **Let the screen rest.** A screen that must be read stays still for at least 1.5 to 2 s.
- **One look.** Light or dark, not both; flat 2D or 2.5D depth over heavy 3D (3D only when it shows a real object); the brand palette; glass, glow and gradients only if they match the brand.
---
## Lifehacks for UI in AI video and images
What practitioners and Lyra's own templates do to keep UI exact (2026):
1. **Start from the sharpest possible source.** Full-resolution PNG screenshots of the current version; small type blurs and shifts first, so the screen should take a large part of the frame (about half the frame height or more for a read moment).
2. **Clean the screenshot before anything else:** no personal data, notifications, carrier names, debug bars or placeholder text; full battery and signal icons. Ask the user for a clean one rather than letting a model "fix" it.
3. **Crop and compose at the video's ratio** (9:16) with margin around anything that will move, so the model never has to extend the picture by inventing content.
4. **Give every image one job, and say it.** "[the first frame] is the exact start of the clip; [the last frame] is the exact end"; "[Image2] is the phone screen; reproduce it exactly". An image without a stated job leaks or gets redrawn.
5. **Name the anchors, briefly.** "keep the layout, every text, icon and color exactly as in the image"; then list the 3 to 5 most important visible texts in quotes so the model and the checker know them.
6. **Lock the camera, then add one move.** Test in steps: first the UI still with only light moving; then one slow push-in; then one small action (a tap). If the UI drifts, reduce motion before changing anything else.
7. **Use a carrier.** Let one stable element (the phone outline, the logo, a light source) persist through the shot; viewers track it and small artifacts hide.
8. **Hard change → two passes.** For a big transformation, generate a stable midpoint first (A → mid, then mid → B with first + last frame) and cut them together, instead of one clip that morphs.
9. **Short beats long.** UI clips around 4 s (Lyra's own tip); a 4 to 6 s clip is trimmed to the 1.5 to 3 s that look perfect.
10. **Overlay what must be exact.** Generated footage carries the scene, motion and light; the exact screenshot, logo, price or legal line goes on top as a layer for the moment it must be read (the phone static or nearly static under it).
11. **Change one variable per rerun** (motion, wording, or the frame), never several, and never rerun an unchanged prompt.
12. **Check three frames of every clip:** the first, the middle and the last. Text that is right at the ends can still wobble in the middle.
13. **End every prompt with "no new text, no captions, no subtitles, no watermark, no UI redesign".**
---
## Step 1 additions: assets and fidelity map
1. **Brand Kit** as in base Reference I, plus what UI work needs most: brand colors (hex), positioning, the offer and CTA, store links, the real store rating if one may be shown, must include / must exclude, forbidden claims.
2. **Ask for the assets in one message** (screenshots only), together with the screen questions above (which screens, order, where to tap, what appears after):
- **2 to 5 clean screenshots** of the key screens, current version, full resolution (PNG).
- For a state change (button pressed, toggle, result appears): **two screenshots, before and after**.
- For other markets: **screenshots of the localized app**, one set per language (UI is never machine-translated).
- **Logo** (transparent PNG), **app icon**, the **end card** if they have one, the brand font name.
- **Official store badges** ("Download on the App Store", "Get it on Google Play") as files, if the end card uses them; never generated.
3. **Fidelity map** (a user text node "Fidelity map"): for every element, one line: element · source file · rung · model · allowed motion · the exact texts on it. Example:
> Hero screen "Tonight's plan" · screenshot 2 · frame · seedance-2.0 · float + slow push-in · texts: "Tonight's plan", "Wind down", "5 min", "Start"
> Button "Start" pressed · screenshots 2 → 3 · first + last frame · seedance-2.0 · one tap · texts: "Start" → "Breathing", "5:00"
> End card · end-card.png · frame, then layer · seedance-2.0 · icon bounce, button pulse · texts: "Calmly", "Sleep in 5 minutes", "Install"
> Logo · logo.png · layer · none
4. **Defaults (state, don't ask):** Reels / TikTok · 9:16 · **15 s** (6 to 20 s for social) · English · no person on camera unless the concept needs one · voiceover on, or music-led with captions added in the Video Editor · music on, instrumental · **Seedance 2.0 with frames, 720p** (1080p on the user's choice), sound on · Nano Banana Pro for every design frame, 9:16, 2K · clips 4 to 6 s joined in the Video Editor · **store-style end card** 2 to 3 s at the end.
**Recommended first run:** A. Design frames (every frame the clips start or end on, the phone shots and the end card; cheap, and they decide whether the UI is right).
## Step 2 addition: the concept
Per video: **product moment** (one screen or result) · **style** (style library) · **look** (light / dark, palette, depth) · **shot list** with timing, each shot's element, rung, model and motion · **text plan** (every headline, caption and CTA line word for word, all marked "Video Editor") · **audio** (VO words counted, or music-led) · **end card** (iOS, Android or both).
> C1 · floating hero phone · Calmly · dark navy, violet glow, 2.5D · 0 to 2 s: the phone already drifting up into frame, screen "Tonight's plan" (frame, 2.0) · 2 to 6 s: slow push-in, a finger taps "Start", the screen switches to "Breathing, 5:00" (first + last frame, 2.0) · 6 to 9 s: the timer card lifts slightly off the screen (frame, 2.0) · 9 to 12 s: brand motion background, three lines land one by one in the Video Editor: "5 min", "No ads", "Works offline" · 12 to 15 s: store-style end card, icon bounce, "Install" pulses (frame, 2.0; badge as a layer) · VO 30 words · music: soft electronic, 90 BPM, hit on the tap.
The first frame is already moving and reads as a thumbnail. For a test with several openings, take hooks from `lyra-video-hooks`.
---
## Style library
A reference, not a menu. Combine and adapt.
| Style | What it looks like | Good for | Build note |
|---|---|---|---|
| **Floating hero phone** (default) | a phone with the real screen in a clean brand-colored space, slow push-in, light sweep on the glass | any app with one strong screen | design frame → Seedance 2.0 first frame, 5 s, micro-motion |
| **Hand or robotic hand showcase** | a hand holds the phone to camera, only micro-movements, the screen stays front-facing | premium, tech | Lyra template "Robotic Hand Showcase"; the hand barely moves |
| **Tap-through micro-demo** | a finger taps one button, the screen changes to the result | the core action | screenshot A and B as first + last frame; one tap; 4 to 5 s |
| **Card stack / fan-out** | several screens as floating cards in depth, sliding in one after another | several features at a glance, one per card | one clip per card (frames), or cards as layers over a brand motion background |
| **UI pop-out** | one element (a card, a chart, a badge) lifts out of the screen toward camera | the "aha" result | first frame flat, last frame with the element lifted; small distance; its text checked |
| **Kinetic type + UI** | short bold headlines land between screens or beside the phone | a big idea, sound-off viewing | headlines in the Video Editor; screens as frame clips; one line at a time |
| **Brand motion background** | gradients, waves, shapes, particles in brand colors behind layered UI and logo | end cards, transitions, budget builds | the only prompt-only clip; no text, no logo; everything readable laid on top |
| **Screen to world** | the UI expands from the phone onto a billboard, a wall, a sky screen | launches, scale | the screenshot placed into the scene with Nano Banana Pro ("replace the image on the billboard with the second reference image"); Lyra template "Global Billboard Swipe" |
| **Person + phone moment** | a realistic person uses the phone, the screen is the hero for a moment | when a human reaction sells it | `lyra-ugc-video` for the person; the phone shot and UI insert by this file |
| **Store-style end card** | the closing 2 to 3 s: icon, name, benefit line, rating, install button, store badge | **the end of almost every app ad** | see below |
**Lyra templates that fit** (re-check `list_templates`; search by title): **Robotic Hand Showcase** · **Phone Screen Reveal** · **Global Billboard Swipe** · **Billboard App Reveal** · **Swipe Away the Chaos**. When adapting: keep 720p by default, 1080p on the user's choice (some run at 720p), switch UI clips to Seedance 2.0 with frames, replace the template's uploads with the user's screenshots and logo, remove stacks like "8K, hyper-detailed", keep the fidelity lines.
---
## The phone shot: screenshot + character or scene in one image
Whenever the screenshot is combined with a person, a hand, a phone on a backdrop or a place (base Reference D, UGC phone moments, screen to world), the combining happens in **one Image Generation node** (Nano Banana Pro) with the character or scene image and the screenshot connected:
- The prompt gives each input its job: "[Image1] is the woman: face, hair, hoodie, room and light. [Image2] is the app screen: display it on the phone exactly as supplied."
- Fidelity line, always: "Preserve the screen exactly: the same layout, typography, spacing, icons, colors and every word and number. Do not redesign, simplify, translate or add anything to the interface."
- Then list the key visible texts in quotes ("Tonight's plan", "5 min", "Start").
- Phone almost front-facing to camera (tilt up to about 15°), the screen large, no fingers or reflections covering text, a generic modern phone without a brand logo.
- **Check with the user before any clip:** "Compare the phone screen with your screenshot word by word: titles, buttons, numbers, small labels, icons, colors. Anything different?" Even one wrong character → rerun the image (cheap), with the wrong text named in the prompt ("the button reads exactly 'Start', not 'Stat'").
- After two failed reruns: make the screen larger in the frame and simplify the pose; if it still fails, keep the screen turned away in the person's shot and show the UI as a separate Seedance 2.0 frame insert or as the screenshot layer.
## The store-style end card (packshot)
Most app ads end on a short **back shot / end card styled like the app's store page**: the app icon, the app name, a short benefit line, the rating, an **Install / Get** button and the App Store or Google Play badge, in the brand's colors. It is the CTA moment, 2 to 3 s, and it should be on almost every ad.
**What goes on it (all from real data):**
- App icon and app name exactly as in the store.
- One benefit line or the offer (≤40 characters), from the Brand Kit ("Sleep in 5 minutes", "7 days free").
- Rating and review count **only if real** and the user or Brand Kit gives them; otherwise leave the rating out.
- Button: "Install" (Google Play style) or "Get" (App Store style), or the brand's CTA ("Try it free"). One CTA.
- The **official** store badge files from the user, as a layer; never generated, never redrawn.
**Platform versions.** Make an **iOS version** (App Store badge, "Get") and an **Android version** (Google Play badge, "Install") when the campaign runs on both; everything else identical. The card is styled *like* a store page (clean white or brand background, rounded icon, button shape), not a copy of the real store screen, and never shows fake numbers, fake reviews or the OS system UI.
**How to build it:**
1. **The user has an end card file** → it goes in as an image layer for the last 2 to 3 s (rung 1); for a little life, the same file as **first frame on Seedance 2.0**, 3 to 4 s: "the app icon bounces in slightly and settles, the Install button pulses softly once; every text and the layout stay exactly as in the image", then the original file as a layer for the final hold if any letter drifted.
2. **No end card** → design it as an image (Nano Banana Pro, 9:16): the uploaded app icon connected, every text written in the prompt in quotes, brand colors, generous space; the store badge left out of the image and added as a layer. **Check every letter with the user**; then animate it as above.
3. Text the end card needs that isn't in the image (a price, a disclaimer) → Video Editor text, never generated.
---
## Best way to build it
The user's explicit choices override any row. Models and prices: base Reference A.
| If the video is | Best approach (graph) | Models |
|---|---|---|
| **Default: 15 s UI motion ad** | uploads (screenshots, logo, icon, badges) → one design frame per shot (screenshot connected, "exactly as supplied") → **one Seedance 2.0 clip per shot, 4 to 6 s, design frame as first frame** (+ last frame for a state change), motion-only prompt → end card (frame clip) → Video Editor: clips in order + text and layers + VO + music | nano-banana-pro · seedance-2.0 |
| **A lot of person, some UI** (UGC, talking head, lifestyle) | character image + phone shot → main clip on **Seedance 2.5** (both as references) → UI check with the user → if the screen came out wrong (or the UI moment is planned as important), a **separate UI-only clip on Seedance 2.0 with the phone shot as frame**, laid over that moment in the Video Editor | seedance-2.5 + seedance-2.0 |
| A lot of UI in one ad | split: one clip per screen or state, Seedance 2.0 frames, joined in the Video Editor; no clip carries more than one screen change | seedance-2.0 |
| A state change | screenshot A and B (or checked design frames of both) → first + last frame, one tap | seedance-2.0 (kling-v3-video Pro as alternative) |
| A screen that must be read word for word | the clip moves the phone; for the read moment, the exact screenshot laid over the screen area (phone still), or a 1.5 to 2 s hold of the design frame as an image clip | video_composer |
| Headlines, offer, CTA, captions | Video Editor only (text tool, or a transparent PNG text card from the user's designer); never in a generation prompt | video_composer |
| Animate an existing static ad or end card | the image as first frame on Seedance 2.0; the prompt says what moves when and what stays | seedance-2.0 |
| Many variants, tight budget | design frames for all; clips on seedance-2.0-fast (720p) for tries; the winner rerun on seedance-2.0 (720p, or 1080p on the user's choice) | seedance-2.0-fast |
| Store screenshot set | see "Store screenshot sets" below | nano-banana-pro |
**Why several clips here, not the base skill's one clip.** UI needs exact frames per shot, one of the base skill's reasons to split (Step 2); say it in one line of the plan. **Connections (base Step 4):** connect the whole graph at build time. An uploaded screenshot can be a first or last frame right away; a generated design frame becomes a frame link right after it has a result (say this in the plan and make the link automatically before running the clip). Keep count 1 on design frames when the user picks option C.
**Design frames.** The exact picture a clip starts (or ends) on, made before any video: Nano Banana Pro, 9:16, 2K, the screenshot connected; the screen shows **the reference image exactly as supplied**; the phone almost front-facing, the screen large; the background from the brand palette; space left for the text that comes later in the Video Editor, inside the safe zone. When the shot is just the screen itself (no phone), the uploaded screenshot can be the frame directly, with no image generation at all: the safest option.
**Video Editor.** One `video_composer` per final. Video tracks in playback order; image tracks above for screenshots, text cards, logo, badges (position x/y/width/height, duration, opacity). Layers are static. Clip sound muted or lowered under VO and music. All headlines, captions and the CTA are added here; tell the user exactly which text to add or check and where. End card 2 to 3 s at the end.
**Layout.** Section "Assets" (uploads + "Fidelity map") → Section "Design frames" (phone shots, end card) → Section "Clips" → Section "Audio" → Section "Final". Labels: "Frame: hero phone · Tonight's plan", "Clip 2: tap Start (A→B)", "End card: iOS", "Final: C1 · floating hero phone".
## Run options
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes, per option. **A. Design frames (recommended):** phone shots, design frames and end card, count 1 (2 for the hero frame if the user wants a choice) · **B. Clips** for the frames the user approved, with VO and music · **C. Everything** → the Video Editor. C only if the user accepts unchecked frames; the fidelity check is why A comes first.
---
## Store screenshot sets (App Store / Google Play)
Static images, not video: a set of store screenshots built around the app's real screens, plus variants to test. Same fidelity rules; here the screenshot is the product.
**Specs (check App Store Connect and Play Console before export; they change):**
| | App Store (iPhone) | Google Play (phone) |
|---|---|---|
| Size | 6.9" base: **1320 × 2868** or **1290 × 2796** px portrait (6.5": 1284 × 2778); exact pixels required | **9:16**, at least **1080 × 1920** for recommendation eligibility; any side 320 to 3840 px, long side ≤ 2× short side |
| Count | up to **10** per localization | **2 to 8** per device type (at least 4 for large-format eligibility) |
| Format | PNG (best for UI text) or JPEG, RGB, no transparency | JPEG or 24-bit PNG, no alpha |
| Content | must show the real in-app UI; device frames optional but must not misrepresent the UI; no "#1" / "best", no "Download now", no mention of other platforms, no URLs or QR codes | the real in-app experience; text ≤ 20% of the image, no small text; **no** "Best", "#1", "Top", "New", "Discount", "Sale", "Million downloads"; **no** "Download now", "Try now"; **no** store badges, device imagery or third-party logos; clean status bar |
**What a good set does:** the first 2 to 3 screenshots carry the main value (most visitors never scroll); one message per screenshot: one short caption (2 to 6 words, large, high contrast) + one UI focus; the set tells a story from the main benefit to supporting features; one consistent style (background, type, caption position); localized per market from localized app screenshots.
**How to build it in Lyra:**
1. Plan the set in a text node "Store set": per slot, the screenshot file, the caption word for word, the background, device or no device (Google Play: no device frame).
2. One Image Generation node per slot (Nano Banana Pro, the screenshot connected, the tallest ratio `list_node_configs` offers for the App Store, 9:16 for Google Play, the highest resolution): "Place the supplied app screen exactly as supplied, unchanged, [in a modern phone / as a flat screen with rounded corners] on a [brand background]. Caption at the top, exactly: '…'. No other text." The caption is the only text the image model writes; everything on the screen comes from the screenshot.
3. **Check every slot with the user**: the screen identical to the screenshot, the caption spelled right. Rerun what fails, naming the wrong text.
4. Exact pixel sizes: adapt with the Image Resize node (`lyra-adapt-image`) where it gives the target ratio; for exact App Store pixels the final crop or canvas is set in a design tool by the user's designer. Say this up front.
5. Never use the Image Translation node on screenshots with UI: it would translate the interface. Other languages = the localized app's screenshots + the caption written in that language.
**Variants to test** (Apple Product Page Optimization, Google Play store listing experiments): change one thing per variant: the **first screenshot** (which screen leads) · the **caption angle** (outcome "Sleep in 5 minutes" vs feature "Guided wind-down timer") · the **style** (light vs dark, device vs flat screen) · the **order** of the set. Different ideas = different nodes; more takes of one idea = `count`.
---
## Prompt rules (UI)
| Node | Write | Avoid |
|---|---|---|
| Fidelity map (text node) | every element with source, rung, model, motion and its exact texts; the shot list; every Video Editor text line word for word | text meant to be generated |
| Design frame / phone shot (image) | each input's job → the device and how it's held or placed → "the screen displays [ImageN] exactly as supplied; preserve the layout, typography, spacing, icons, colors and every word and number; do not redesign, simplify, translate or add anything" → the key texts in quotes → backdrop from the brand palette → soft light, controlled glass reflections → composition (screen front-facing, large, legible, space for editor text, central 65%) → "no other text, no captions, no watermark" | "8K, hyper-detailed" stacks; a phone brand logo; extra UI or widgets; strong tilt; fingers or glare over text |
| UI clip with a frame (Seedance 2.0) | task line → "Treat the image as frame 0; keep the layout, every text, icon and color exactly as in the image" → timeline: what moves, when, one element at a time, small amplitudes → **what stays still** → camera (locked, or one slow push-in) → end state, "holds in final position" → sound line → avoid line → the list of texts visible in the last frame | re-describing the look; rotation, flips, orbits; any new text, numbers or captions; several elements at once |
| Clip with first + last frame | "The first image is the exact start, the last image is the exact end. Continuous transition: …" one physical cause (a tap, a slide); what stays identical in both | a third state; motion the two frames don't explain |
| Brand motion background | abstract shapes, gradients, light and particles in the brand colors, slow looping motion, empty center | any text, letters, numbers, logos, icons, UI |
| Sound line (every clip) | "Sound: only soft UI sounds (a light click on the tap, a soft whoosh); no music, no speech, no voice" | leaving it open |
| End card image | the icon connected; app name, benefit line, button label in quotes; brand colors; space for the badge layer | generated badges, ratings that aren't real, more than one CTA |
| VO and music | base Reference C | artist names; VO repeating what the viewer reads |
**Pattern: UI clip from a frame (Seedance 2.0, first frame).**
> Short motion design shot for an app ad. Treat the image as frame 0: keep the phone, the screen layout and every text, icon and color exactly as in the image. 0 to 1 s: the phone drifts up a few centimeters and settles. 1 to 3 s: the camera makes one slow push-in toward the screen. 3 to 4 s: the "Start" button glows softly once. 4 to 5 s: a gentle light sweep crosses the glass; everything holds in its final position. The screen content, all text and the icons stay perfectly still and sharp the whole time; only the phone, the light and the button glow move. Sound: only a soft airy whoosh and a light click; no music, no speech. Avoid: new text, captions, subtitles, text morphing, letters changing, extra icons, UI redesign, rotation, perspective distortion, flicker, warping, watermark. Text visible in the last frame: "Tonight's plan", "Wind down", "5 min", "Start".
**Pattern: phone shot (Nano Banana Pro, two inputs).**
> UGC phone photo. [Image1] is Mia: her face, curly hair in a loose bun, grey hoodie, her dark bedroom and warm lamp light. [Image2] is the app screen. Mia holds a modern smartphone close to the camera, screen facing us, almost straight on, her thumb at the lower edge away from any text. The phone screen displays [Image2] exactly as supplied: preserve the layout, typography, spacing, icons, colors and every word and number; do not redesign, simplify, translate or add anything. Visible on screen: "Tonight's plan", "Wind down", "5 min", "Start". Natural skin texture, phone-camera look, deep focus, soft lamp light, no glare over the screen. No other text, no captions, no watermark, no phone brand logo.
---
## Truth and fidelity
- UI only from real, current screenshots; no screen, feature, number, result or badge the app doesn't have. The ad promise matches the store page.
- Ratings, review counts, awards, "#1", user counts: only real, from the Brand Kit or the user, and only on the end card or as editor text.
- Store badges: only the official files; no OS system UI copies; no third-party logos or real phone brand marks.
- **Ads, not store previews.** A generated motion video is a paid ad. Apple's App Store preview videos must use real screen captures of the app; Google Play's preview video should show the real in-app experience. If the user wants a store preview video, say so and suggest a cut from real captures.
- **Brand safety** (Lyra's System Preamble, base Reference B): no profanity, no political statements, no unsubstantiated health claims, no competitor disparagement. The Brand Kit's **forbidden claims are enforced absolutely**, in every headline, caption, end card, visual and VO; if the user asks for one, say once that it is on the kit's forbidden list and leave it out unless the user confirms the kit is outdated.
## Common mistakes (UI)
| Mistake | Prevention |
|---|---|
| The model "fixes", simplifies or redraws the UI | Screenshots only; "exactly as supplied" in every prompt; check before clips |
| A UI video planned without asking which screens, in what order, where to tap | Screen questions first (Screens: ask first) |
| The next screen or a new state invented when there is only one screenshot | One screenshot → one-screen video; ask for the after-screenshot |
| More screens pushed after the user said one is enough | One screen, done well |
| A blurry or compressed screenshot used as is | Ask for better originals, or improve in Nano Banana Pro and check word by word |
| Pixel-perfect UI promised in a moving shot | Say once that UI is hard; aim for the first or second run; fix only the broken piece |
| A wrong letter in the phone shot carried into the video | Word-by-word check of every combined image before any clip |
| Text morphs during the motion | Seedance 2.0 frames, smaller motion, shorter clip, or a layer for the read |
| Subtitles, headlines, price or CTA written into a video prompt | Video Editor only |
| Seedance 2.5 or references used for a UI insert | Seedance 2.0 with frames |
| Seedance 2.0 forced on a person-led video | Person leads → Seedance 2.5; UI fixed with a 2.0 insert if needed |
| UI in a 2.5 person clip not checked | Check the screen on the first, middle and last frame with the user before the edit |
| Image connected as a frame on Seedance 2.5 (error) | 2.5 = references only |
| One long clip carrying the whole UI story | One screen or state per clip, 4 to 6 s, joined in the Video Editor |
| Screen-to-screen morph with only one state given | First + last frame, one tap as the cause |
| Rotation, orbit or deep 3D around a readable screen | Push-in, drift, slide, glow |
| Store badge, rating or review count generated or invented | Official badge files as layers; real numbers or none |
| No end card, or an end card with three CTAs | Store-style end card on every ad, one CTA |
| Image Translation used on UI screenshots | Localized app screenshots; only captions are written per language |
| Store screenshot with "Download now", "#1", badges (Google Play) | The store rules table |
| 1080p without the user choosing it | 720p by default; 1080p on Seedance 2.0 when the user picks it |
## Quality gates (UI)
- **Stage 0 (concept, Claude checks before sending):** screens, order and tap points confirmed with the user, and nothing planned beyond the screenshots received? Screenshot quality checked (better originals asked for, or improved and checked)? The "UI is hard" line said once? One product moment? Every element on the lowest rung it can live on? Seedance 2.0 with frames for every screen-led shot and insert, Seedance 2.5 for person-led clips with a UI check planned? A lot of UI split into short clips? No text in any video prompt except the "keep exactly" lines? Every editor text line written word for word? End card planned?
- **Stage 1 (design frames, phone shots, end card):** every word, number and icon on the screen identical to the screenshot? Nothing added, nothing missing? Screen large and legible at phone size? End card texts spelled right, rating real or absent? Look on brand?
- **Stage 2 (clips):** pause on the first, middle and last frame: does any letter, number or icon change? Only the planned elements move? Smooth, no flicker or warping? State changes match the after-screenshot? Ends held on the planned frame?
- **Stage 3 (final):** first frame moving and readable? One product moment clear in one watch? Readable screens rest long enough? Editor text one line at a time, in the safe zone, the same words as the VO? End card 2 to 3 s with the right badge per platform? Music under VO, no clip music? 9:16, planned resolution (720p by default), planned length? Named with its code?
- **Store sets:** every screen identical to its screenshot? Captions spelled right and within the store rules? Sizes exact for each store? First 3 slots carry the main value?
## Deliverable and naming
1. A "Fidelity map" text node.
2. Design frames, phone shots, the end card (iOS / Android), clips and the Video Editor.
3. One finished video per concept; or a store set per platform and variant.
Videos: `B{batch}-A:{angle}-F:UIMotion-{style}-C{concept}` (add `H{n}` when a hook from `lyra-video-hooks` opens it; add `-iOS` / `-Android` for end card versions), e.g. `B4-A:PlanInOneTap-F:UIMotion-HeroPhone-C1-iOS`. Store sets: `Store-{iOS|GP}-{locale}-V{variant}`, e.g. `Store-GP-en-V2`.
## After the test
Read it as in `lyra-video-hooks` (After the test). The style, the product moment and the end card are hypotheses: say which won. Store sets: judge by store conversion (page view → install) in Product Page Optimization or store listing experiments. Then offer: the winning style on another feature, a UGC version of the same moment (`lyra-ugc-video`), new hooks on the winner, other sizes (recompose 4:5 or 1:1, don't crop) or languages (localized screenshots, new editor text).
---
## Store requirements
Store requirements (sizes, counts, content rules) change: check them in App Store Connect and Google Play Console before export.
lyra-video-ad-generation61.5 KB
View saved version →
---
name: lyra-video-ad-generation
description: "Base skill for video ads in Lyra. Builds a mobile app video ad end to end (brief, script, scenes, keyframes, clips, voiceover, music, Video Editor assembly) with scene consistency, de-slop and error handling. Use for \"a 15-second video ad for my app\", \"a 30 s / 1 min ad\", \"a sequence of scenes\", \"stitch these clips\", or a script or storyboard to produce. Holds the core video rules the smaller lyra video skills point to."
---
# lyra-video-ad-generation
The main video skill for Lyra. It holds the core rules for every video ad: script, scenes, music, voiceover, consistency between scenes, de-slop and error handling. Smaller video skills (UGC, hooks, templates) point here for these rules.
Part 1 is shared by every Lyra skill. Part 2 is what's specific to video ads. The Reference library at the end has the details (models, prompts, audio, UI, consistency, de-slop, errors, Meta app ads).
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**Assembly and captions → `lyra-video-editor`.** Stage 3 of every video (the Video Editor: edit, mix, end card, text, captions, render, cutdowns) follows `lyra-video-editor`. This file only says which pieces go into the edit.
---
# Part 1. [SHARED] How every Lyra skill works
**Deliverable:** a Lyra workflow in which every planned node has been generated. The user opens the canvas and finds the results, the prompts that produced them, and a graph they can edit and rerun for the next app, angle or market.
A full creative always follows these steps, in order:
1. **Context.** Read the Brand Kit, then send the intake quiz (Step 1) so the user takes part in the key choices; make sure you have everything before proposing anything.
2. **Concept and plan.** A very short concept plus a short plan of nodes, models and connections, based on "Best way to build it".
3. **Approval.** One message: concept, plan, open questions and the cost in credits; the user approves or corrects. Nothing is created before this; the yes also starts the run.
4. **Build.** Create the workflow and nodes with the chosen models, write every prompt into the node's prompt field. Nothing runs yet.
5. **Pre-run check.** Right before every run, read the workflow back and restore anything lost (connections, settings); keep the user's own edits.
6. **Credits and run.** The cost is part of the plan; after the one yes, build and run everything without asking again.
7. **Run and report.** Run, report with the right links (workflow, video or image) and the real spend, offer the next step.
8. **Verify quality.** Check with the user against the quality gates.
## Whose instructions win
1. The user's explicit instructions in this chat.
2. This skill's best practices and defaults.
3. The brand kit: real app facts, claims, value proposition, features, audience.
Best practices are defaults, not rules for the user. When a user's choice will likely hurt the result, follow it and say once in the plan what you'd do instead and why; don't argue twice. When a choice breaks a hard limit (a 60 s clip from a model capped at 30 s), explain and offer the closest build that works.
## Step 1. Context
**App.** Every concept starts from the app. Generic ads come from missing product context, so never fill gaps from imagination.
1. Brand kit given in the chat → use it. Otherwise `list_brand_kits`: one kit → "Make this for {kit name}?"; several → ask which. The user may add or override details in chat.
2. No kit → ask once: send it here, or should I check / connect one of the kits already in your workspace? If the user prefers to type it: app name, what it does, who it's for, the pain it solves, 2–3 features the ad may show, approved claims and offer, forbidden claims, tone, assets (logo, **screenshots only**; never ask for a screen recording).
3. Keep the result as an **app card** for the whole session:
> App card: Calmly · 5-minute wind-down sessions for sleep · for students 18–25 · pain: can't switch off at night · may show: wind-down timer, sleep sounds · claims: none approved · tone: calm, a bit ironic · assets: logo, 3 screenshots · source: brand kit
**Intake quiz: involve the user before deciding.** When the user gives a task for a video (a brief, a TZ, "make a 15 s ad for my app"), don't decide everything yourself. After reading the Brand Kit, send **one short quiz** with every open question at once, so the user takes part in the key choices and understands what will be made and why. Lyra's own nodes never ask; this skill does, once, here.
- **Format:** multiple choice. Use the client's question tool (a multiple-choice question card) if there is one; otherwise a numbered list, each question with 2–4 short options (a, b, c), the recommended option first and marked "(recommended)", plus "your own answer". The user can reply "1a 2c 3b".
- **Size:** 4–8 questions, only the ones that matter for this video. Skip anything the task or the Brand Kit already answers; say in one line what you took from them ("From the Brand Kit: audience 25–40, offer 7 days free").
- **Options come from the Brand Kit**, not generic: real pains, real personas, real features, the real offer.
- **Question bank** (pick the relevant ones, in this order):
1. **Idea:** 2–3 short concept options built on different pains or angles (one line each, the hook in quotes) + "my own idea".
2. **Format:** person talking to camera (UGC) · a short story with scenes · animated / 3D · app screens in motion · POV.
3. **Who is on screen:** 2–3 personas from the audience (age, vibe, place) · no person.
4. **Length and placement:** 10 s · 15 s (recommended for Reels / TikTok) · 30 s · 60 s.
5. **Voice:** the person speaks on camera · voiceover · music and text only; language.
6. **Music:** 2–3 moods that fit the idea · no music.
7. **App on screen:** show real screens (then ask for screenshots) · no UI.
8. **CTA / offer:** the Brand Kit's offer · a plain "Download" · other.
9. **Captions:** yes (recommended when someone speaks) · no.
10. **Model and quality:** Seedance 2.5, 720p (recommended, ≈ X credits) · 1080p (sharper faces and details, ≈ 2.4× the price) · a cheaper model.
- **Skip the quiz** only when the user says "just do it", "surprise me", or the task already answers everything: then state the choices in the plan in one line each.
- After the answers, Step 2 explains the plan in plain words (below).
**Task.** The intake quiz covers the inputs in Part 2 → Inputs and defaults; the defaults are its recommended options. Everything in one message; never re-ask what the user said. Call `list_workspaces` (credits) and `list_node_configs` (models) now.
## Step 2. Concept and plan
Short: readable in under a minute.
**Concept:** 2–4 lines per deliverable (Part 2 → Concept). N deliverables = N distinct ideas; more takes of one idea is `count` on a node, not more nodes.
**Explain it in plain words** before the node table, so a user who has never built a workflow understands what will happen: what the video will show, second by second (hook → middle → CTA) · what Claude will generate and in what order (e.g. "first the character photo, then the phone shot with your screen, then one 15 s clip, then voice and music, then the edit") · why this way (one line: e.g. "one clip keeps the person identical in every shot") · what the user gets at the end and what they can change on the canvas. Short and friendly, no node jargon; the node table follows for those who want it.
**Plan:** name the matching row of Part 2 → Best way to build it in one line, then list the nodes:
| # | Node label | Node · model · key settings | Inputs (role) | Stage |
|---|---|---|---|---|
| 1 | Script (note for the user) | user text | — | — |
| 2 | Character: Mia | image · google/nano-banana-pro · 9:16 · count 1 | — | 1 |
| 3 | Screenshot: timer | upload image | — | 1 |
| 4 | Phone shot: timer | image · google/nano-banana-pro · 9:16 | 2, 3 (references) | 1 |
| 5 | VO: full | audio · elevenlabs/v3 · voice | — | 1 |
| 6 | Music | audio · elevenlabs/music · 20 s · instrumental | — | 1 |
| 7 | Ad: 15 s, 3 shots | video · bytedance/seedance-2.5 · 15 s · 720p · 9:16 · audio on (ambience only) | 2, 4 (references) | 2 |
| 8 | Video Editor | video_composer | 7, 5, 6 | 3 |
**One clip by default.** A Seedance 2.5 clip holds up to 30 s and several shots ("cut to"), so one clip with the character and UI as references is the default. Split into separate clips only when: the ad is longer than 30 s · a UI moment needs its own insert (Reference D) · scenes need different models or exact frames · one shot failed and must be replaced · the user asks. Say in one line of the plan why you split or don't.
Stages: **1** = sources (images, voiceover, music; fast and cheap) · **2** = built on finished images (video, lip-sync) · **3** = assembly (Video Editor / composer).
**Cost:** the plan's total in credits, from Reference A → Credit prices (count and duration included), next to the balance: "≈ 500 credits · balance 47 424".
## Step 3. Approval
**One message, one question.** Everything the user has to decide goes into one message: the concept, the plan with models and quality, any question you still have, and the **cost in credits** with the balance (Step 6). It ends with one question that covers all of it, e.g. "Does the concept, Seedance 2.5 in 720p and ≈ 500 credits (of your 47 424) work for you? After your yes I build the workflow and run everything." (Answers already given in the intake quiz, captions included, are not asked again; if the quiz was skipped, videos with speech include the captions question, `lyra-video-editor` → Captions.) Never a separate question about money or about running.
On corrections, show only what changed, with the new cost, and ask again. Don't create anything in Lyra before a clear yes. This yes also starts the run: after it, build and run everything without asking again (Step 6).
## Step 4. Build the workflow
1. `create_workflow` (or `use_template`, or the user's own workflow, or a variation of an existing one: Variations below), then `assign_brand_kit`.
2. Write every prompt (Part 2 → Prompt rules): brief, script, image and video prompts, voiceover text, music prompt. The script can go into a user text node (`create_user_text_node`) as a note for the user, connected to nothing. A user text node feeds its text into any node it is connected to, so keep this one unconnected (a Note on the canvas can't be connected at all, but the tools can't create one). The text doesn't keep the character consistent: consistency comes only from the character image connected as a reference, plus the anchors written into every prompt.
3. Create every node from the plan with its prompt, its model and settings from `list_node_configs`, and a label that says what it's for ("Scene 2: app demo", "VO: hook"), never "Image 1".
4. **Connect the whole graph now** (`connect_nodes`), so the workflow can run on its own with "run all": character → every image and video node that shows the person (reference) · screenshot upload → the phone image · images → video · clips, voiceover, music → Video Editor **in playback order**. Never leave connections "for after the user approves an image". **References** connect before anything is generated (checked in Lyra). **First / last frame** from a generated image needs that image to have a result first (an uploaded image can be a frame right away): on frame models, say in the plan that the frame link is made right after the image runs, and make it automatically before running the clip.
5. Lay out the canvas by `lyra-workflow-layout` (STEP notes, sections in reading order, colors, check), one section per stage: **Sources** (script note, character, screenshot uploads) → **Images** → **Clips** → **Audio** → **Video Editor**. Put an upload next to the node it feeds, never at the end of the canvas. Don't put the whole graph in one Section.
6. Check `is_valid` and `validation_error` on every node; fix with `update_node` using listed values.
## Variations, not new workflows
A new version of something that already lives in a workflow goes into a **variation of that workflow** (Lyra's **Create variation**), never into a new workflow, unless the user asks for a new one.
- **When:** a new version of a video (another story with the same characters, another angle, hook, person, setting, length or language, a remake of a failed take), more room for another round, splitting the work, or the user asks for several variations.
- **How:** `create_variation` (it copies the whole canvas: nodes, connections and results) with a clear title ("D2 · Dan's turn") → `switch_variation` to it (the tools and runs work on the main variation; Lyra also renames the workflow after it) → `delete_node` the nodes this version doesn't need → update the prompts and add the new nodes → connect → pre-run check → run. Nodes kept as they are keep their results and cost nothing (characters, places, the end card clip). The variation keeps the canvas layout: update the section titles and labels that name what changed (`lyra-workflow-layout`).
- **Check the Video Editor right after `create_variation`:** in a new variation the edit can come out empty or pointing to old results (opening the editor there deletes the tracks), and pinned first / last frame results can be cleared. Read the composition and the frame pins, and rebuild them by `lyra-video-editor` before any render.
- Deleting inside a variation you just made for this version is part of the build and needs no extra ask. Never delete in the original variation or in one the user made.
- **Report:** the workflow link, the name of the variation with the new version, and that the original is untouched in its own variation (to show it again: `switch_variation`, which renames the workflow back).
- **Images:** new statics, sizes or languages can stay in the same variation as new nodes, one Section per set, unless the user asks for a separate workflow or the canvas gets crowded; then a variation, as for video.
- **Open canvas:** before editing an existing workflow through the tools, ask the user to close its tab or switch away (an open canvas can write its old state over the tool edits), and tell them when it's safe to open it again.
## Step 5. Pre-run check
Right before **every** `run_node` (the first run, each next stage, reruns, follow-ups). The canvas changes between build and run: the user edits it, and an edit on the canvas can drop or overwrite connections. A run with a missing input spends credits for nothing, so never trust what you built a few minutes ago.
1. `get_workflow` now, not from memory.
2. Compare it with the plan: every planned edge (source → target) is there · every node that takes images has them as planned (`image_inputs_usage`: references or frames; a frame points to an existing result) · every node `is_valid`, no `validation_error` · no empty prompt · settings as planned (model, ratio, duration, resolution, count).
3. Lost or changed by accident → restore it (`connect_nodes`, `update_node`) and say it in one line ("the link Character → Clip 1 was gone, reconnected"). Changed by the user on purpose (their prompt, model, a node they added) → keep it and use the workflow as it is now; never overwrite their edits. Not sure which → ask before running.
4. Inputs ready: a node runs only when every node it takes from has a result. Never run a node with a missing input.
After the build, tell the user once that the workflow is built and running and that they can edit any prompt on the canvas and rerun.
## Step 6. Credits and run
**Where the prices are.** `get_workflow` returns `credits` on every node: the estimated credits of one run of it (null = free: uploads, Video Editor, notes, user text; a Section shows the sum of its nodes; null on a paid node means a setting is missing, e.g. no resolution on Nano Banana 2: set it). Before the build, estimate with Reference A → Credit prices; after the build, read the real numbers off the nodes.
1. **In the plan (Steps 2–3):** the estimated total and the balance (`list_workspaces`), inside the one approval message.
2. **After the build, before running:** add up `credits` of every node that will run. Within ~15% of the approved estimate and within the balance → run everything, stage by stage (sources → images → clips → Video Editor, Step 7), with no question. More than ~15% over, or over the balance → one short message: the new total, why, and a cheaper option (fewer ideas, lower count, 720p, a cheaper model per Reference A); run after the answer.
3. **Reruns and follow-ups:** give the rerun's credits in the same message as the change ("Changed the prompt; rerunning Clip 1 and the Video Editor, 428 credits") and run, unless the user asked to check first.
4. **After the run:** the real spend (balance before − after) and the new balance.
5. A source image with count 2 (a character, a persona) feeds the next stage with its selected result; say in the report which one went on and that the user can switch (Step 7).
6. The smaller skills' **Run options** sections give the run order and what each stage holds: run all of it in that order, without offering the options. A staged run (the look first, then the rest) only when the user asks for it, or when the plan is expensive and the look should be approved first: then say so in the approval message, with each stage's credits, and run the next stage on the user's yes to the look.
7. No `credits` on the nodes at all (the field is gone): estimate with Reference A, say it's an estimate, and keep the same one-question flow.
## Step 7. Run and report
1. `run_node` on every node whose inputs are ready stage by stage: sources → images → clips → Video Editor last. Pre-run check (Step 5) before each stage. Keep each `run_uuid` and `variation_uuid`; call `get_run_results`; while `in_progress`, call it again. **Never call run_node on a running node** (second paid run).
2. **Picking a result.** A node with several results: when the user names one ("take the second", "the first one"), set it yourself on every node that uses it; don't send the user to tick it in Lyra. On a node with `image_inputs_usage` (video nodes): `update_node` with its whole `image_inputs_usage` from `get_workflow` and one field changed: references → `reference_result_image_uuids: [picked uuid]` (or the other results in `exclude_reference_result_image_uuids`); frames → `first_frame` / `last_frame` = `{"node_uuid": source node, "image_result_uuid": picked uuid}`. The results' uuids and their order (first, second…) come from `get_run_results` of the source node's run. Then `get_workflow` to check it held, and rerun what comes after it (pre-run check first). Only when the node has no such setting or the tool refuses: ask the user to tick it in Lyra and say why. Without a pick, the next stage uses Lyra's selected result; say which one went on.
3. Run a stage only after its inputs have results; the Video Editor runs last.
**Links in every report.** Never only file links. Two kinds of link, nothing else:
- **Workflow:** `https://lyra.splitmetrics.com/workflows/{workflow_uuid}` (opens for anyone signed in to Lyra with access to the workspace; results in a variation: name the variation to open).
- **Result:** the `url` from `get_run_results`, exactly as returned.
- one video → the video link + the workflow link
- several videos → the workflow link only
- one image → the image link + the workflow link
- several images → the workflow link only
A video ad's final is the Video Editor result; clip links only when the user asks.
Report:
> Calmly · video ad · "2 am": done. Video: {video url} · Workflow: https://lyra.splitmetrics.com/workflows/{uuid}. Spent {x} credits · balance {X}. Character: result 1 went into the clip; say "take the second" to switch. Open the workflow to edit any prompt and rerun.
- Name failed nodes: label, what it was asked to do, why if known, the fix you suggest.
- When every node has a result, offer 2–3 next steps (new angle on the same concept, other sizes, other languages).
- After the final result, run `lyra-result-check` straight away, without asking (free): it opens the result in a browser, checks the frames and measures the sound, and reports the problems with pictures and fixes. Never describe or grade a result you haven't seen; without a browser send the stage checklist (Part 2 → Quality gates) and ask what works and what doesn't. Refer to nodes by label, never by uuid.
## Step 8. Verify output quality
Check final assets, not only job status: completeness (outputs, order, scenes, CTA) · message (hook, value, claims, language match the brief) · visuals (continuity, correct UI, no major defects) · audio (words, voice, pronunciation, sync, no clipping) · delivery (duration, 9:16, resolution, final render) · variations (intended differences visible) · reusability (inputs editable). Use Part 2 → Quality gates. Suggest fixes only for identified defects, within authorized scope and cost.
## Follow-ups
- One change ("make her older", "faster music"): `update_node` on that node, show the new prompt, pre-run check, rerun it and the nodes that depend on it (the rerun's credits in the same message, Step 6).
- A new angle, persona, size or language: hand over to the matching skill.
- Never delete or overwrite results the user may want: a new version goes into a variation (Variations above). `delete_node` only inside a variation you just made for this version, or when the user asks.
## Runtime failures
See Reference G. In short: validation_error → fix with listed values · run failed → name it, one retry with a changed prompt or model and its credits · in_progress → poll again · not enough credits → stop, show the balance and what's missing, offer cheaper (Step 6) · model refused content → tell the user, don't rephrase around it · file without public link → ask for a link or upload in Lyra.
## Base prompt rules
You write every prompt, and each lives in its node's prompt field, where the user reads, edits and reruns it. Write for the model and for the person.
- Self-contained: no "same as above", no references to the chat.
- Concrete and renderable: things the model can show or say, not marketing concepts.
- The user's own words for the subject and anything they specified stay as given.
- Settings (ratio, duration, resolution, voice, audio) go in node settings, not in the prose.
- English, unless text must appear or be spoken in another language. Exact on-image or spoken text in quotes.
- No placeholders, alternatives or "if" branches in a final prompt.
## Common mistakes (every skill)
| Mistake | Prevention |
|---|---|
| Builds or runs before concept and plan are approved | Steps 1–3 first, always |
| Asks about the price or the run as a separate question | Cost goes into the one approval message; the yes starts the run (Steps 3, 6) |
| run_node on a running node | Poll get_run_results |
| Plan without a cost, or a run without reading the nodes' credits | Reference A → Credit prices in the plan; node `credits` before the run |
| Runs with lost connections, or over the user's canvas edits | Step 5 pre-run check before every run |
| Sends the user to tick a result in Lyra | Step 7: set the picked result yourself |
| A new workflow for a new version of the same ad | Create variation of the same workflow, delete what this version doesn't need (Variations) |
| Only file links, or no workflow link | Step 7 links |
| Invents app features, UI, numbers or reviews | Only the app card; without screenshots keep the screen out of view |
| Swaps the user's explicit choice for a default | Instruction order; mention the trade-off once |
| On-screen text or captions in video prompts | Text in the script, marked for post |
| Re-describes the look in a video prompt with a first frame | Motion only; the frame sets the look |
| Leaves connections for later, so "run all" breaks | Connect the full graph in step 4; frames at the video's ratio |
| Splits a short ad into a node per micro-scene | One clip by default; split only for the listed reasons |
| Voiceover longer than its clip | Reference C pacing; VO ~1 s shorter than the video |
| Values the model doesn't list | Copy from list_node_configs |
| Nodes for takes of one idea, or count for different ideas | Ideas → nodes; takes → count |
| Prompts that point back to the chat | Self-contained prompts |
| Reruns an unchanged prompt as a fix | Change prompt or model; say what changed |
| Describes or grades results it can't see | Ask the user with the stage checklist |
| A forbidden claim from the Brand Kit, a political line or a dig at a competitor | Brand safety (Reference B): forbidden claims enforced absolutely |
---
# Part 2. Video ad generation: what's specific
## Description
Creates multi-scene video ads for mobile app paid ads in Lyra, SplitMetrics' node-based creative canvas, leaving a generated, reusable workflow on the canvas.
Use when the user asks for "a 15-second video ad for my app", "a 30 s / 1 minute ad", "a sequence of scenes", "stitch these clips together", or hands over a script or storyboard.
Works from a Lyra brand kit or app details in chat, app screenshots, a script, a reference ad (through the Creative Analysis node), or an existing workflow.
Not for: a UGC creator video (the UGC skill), a hook only (the hook skill), static images (the image skills). Those skills use this skill's rules for scripts, scenes, audio, consistency and de-slop.
## Quality bar
Stops the scroll in the first 1.5–3 s, shows only real app features and real screens, reads as one consistent film (same person, place, light), sounds natural (voice not rushed, music without vocals under speech), no AI-slop look, and works with sound off.
## Inputs and defaults
**Required (ask if missing):** the app (brand kit or app card) · what the ad is about or the idea, if the user has one · app screenshots, if the ad shows the app.
**Defaults (the recommended options in the intake quiz; if the quiz is skipped, state them in the plan):** Reels / TikTok · **9:16** (16:9 only if asked) · **15 s** · English · voiceover on · music on (instrumental, its own music node in the Video Editor; never inside a clip where someone speaks) · **Seedance 2.5** recommended for real people, **Seedance 2.0** for illustration / UI-heavy · **720p** by default (1080p only when the user picks it, with its price) · ask which model and quality the user prefers in the intake quiz, with your recommendation and why · **sound on** at generation (mute in the Video Editor if needed) · Nano Banana Pro for keyframes · 1 result per node.
**Run:** everything after the one yes, in stage order (Step 6).
## Concept
A good concept names one pain the audience recognises, in their words, and shows the app solving it with one real feature, one beat per scene, CTA at the end. It also says **why** it should work: the user is trying to learn what works and why (System Preamble). Write it as the hypothesis + beats:
> Video, 15 s. We believe students who can't switch off at night will start a trial because a relatable 2 am POV shows the wind-down timer working. 0–3 s hook: "POV: 2 am, brain won't stop", tired face in phone light · 3–11 s she starts the timer (real screenshot), shoulders drop · 11–15 s eyes close, CTA "Try it tonight". Voice: tired, warm. Music: soft lo-fi, instrumental.
Brief, structure, scene fields, timing and montage rules: Reference B.
## Best way to build it
The user's explicit choices override any column. Model choice and price rules: Reference A.
| If the request has | Best approach (graph) | Models | Why |
|---|---|---|---|
| **Nothing specific (default)**, real people, ≤30 s | character image (+ phone image with the real screenshot if the app is shown) → **one** multi-shot clip ≤30 s with both as **references** → VO + music → Video Editor | seedance-2.5 · nano-banana-pro | fewest nodes, one consistent look; Seedance holds identity from references |
| UGC / creator talking to camera | hand over to the UGC skill; if it runs here: Seedance 2.5 only, never Kling or Veo | seedance-2.5 | Seedance is clearly better at people |
| 60 s or longer than 30 s | full script → two 30 s parts (or split text) with the same character and style references → two clips → Video Editor | seedance-2.5 | no model makes 60 s in one clip |
| Illustration, cartoon, stylized, moving text | keyframe per scene → clip with image as **frame** | seedance-2.0 | holds style; frames keep the picture exact |
| The app's UI on screen | user screenshots → phone image (character + screenshot) → short clip, or UI insert laid over in Video Editor (Reference D) | seedance-2.0 (frames) or seedance-2.5 (refs) | models break UI in long busy clips |
| Exact start and end frame, complex multi-shot | first + last frame per clip | kling-v3-video (Pro) | precise frame control (not for UGC) |
| Very short product / nature shot, ≤8 s | references → one clip | veo-3.1 | realism; max 8 s, used rarely |
| Copy a movement from a reference video | character image + motion video | kling-v3-motion-control | motion transfer |
| A reference ad to adapt | Upload Video → Creative Analysis → script (written by you from its output) → as default row | as default row | keeps the mechanism, not the identity |
| Many drafts / tight budget | draft model for tries, rerun the winner on the recommended model | seedance-2.0-fast, veo-3.1-lite | spend on the winner only |
## Prompt rules
| Node | Write | Avoid |
|---|---|---|
| Image (keyframe) | concept in 2–3 words → subject → action → setting → framing → light → color/lens → mood → style → visible details → exclusions in plain words. ≤500 chars. The moment it shows (start of the motion if used as first frame). | abstract adjectives; text; drawing the user's logo or UI |
| Video with a frame | motion only: what moves, camera move, pacing, end state; spoken line in quotes if the model speaks | re-describing the look; on-screen text |
| Sound line (every clip) | **no music in a clip where someone speaks** (Reference C). With speech: "Sound: dialogue and the natural sounds of the scene only (room tone, steps, a door, a cup on the table); no music, no background music, no soundtrack, no score, no song, no humming". Add "background music" to the Avoid line too. Without speech: no music ban needed (music from the generator can be muted in the Video Editor); with a separate voiceover and nobody speaking on camera: "no speech, no voice" | a clip with speech and no sound line (the model adds its own music under the voice) |
| Video with references | who is who first ("[Image1] is the character's face and outfit, [Image2] is the phone screen"), then scene and motion; must-keep identity early | mixing frames and references on Seedance; unassigned references |
| Video without image | full scene as for an image, then the motion | more than one scene per clip unless multi-shot with "cut to" |
| Voiceover | exact words only, one continuous text, numbers as spoken, sized to the video at the right pace, ~1 s shorter than the video | stage directions, labels, brackets; lines longer than the clip |
| Music | genre, era, BPM, instruments, energy curve (hook hit → build → CTA resolve), "instrumental only, no vocals" when anyone speaks, length = video + ~5 s | artist names; vocals under speech; length equal to the ad |
**Prompt length:** one shot 60–150 words (sweet spot 80–120); image-to-video 40–60% shorter; over ~300 words later instructions get ignored. Non-negotiables first.
**The 5 rules that matter most here:** (1) one scene, one main action, one camera move; (2) anchors repeated word for word in every prompt (Reference E); (3) no generated text or UI, ever; (4) style from the brief, phone-real for UGC, no "stunning 8K" adjectives; (5) plan the end frame of every clip.
Full prompt craft (nine blocks, video formula, camera, light, materials, physics, phrase bank, worked example, checklist): Reference F.
## Common mistakes (this skill)
| Mistake | Prevention |
|---|---|
| Image connected as first/last frame on Seedance 2.5 (error) | Seedance 2.5 = references only |
| Character's face changes between scenes | Character image first, passed as reference to every scene; same model for all clips |
| UI on the phone garbled or invented | Real screenshots only; phone image + UI insert (Reference D) |
| 1080p used without the user choosing it | 720p by default; 1080p only when the user picks it in the quiz or asks, with its price |
| Decides the idea, person, voice and music alone | Step 1 intake quiz with options from the Brand Kit; explain the plan in plain words |
| Music fades out early / has vocals under the voice | Generate ~5 s longer, instrumental, trim in Video Editor |
| Voiceover runs over the video | Words for (video − 1 s) at a calm pace; shorten text or faster voice, never regenerate video |
| Artist name in the music brief (error) | Describe genre, tempo, mood |
| Sound turned off at generation | Keep sound on; mute in Video Editor |
| Kling or Veo offered for UGC | Seedance 2.5 always for UGC |
| Claims a text brief/script node keeps the character consistent | A text doesn't make the character consistent; consistency = character image as reference + anchors |
| Clips where someone speaks come with their own background music under the voice, a different track in each | The no-music sound line in every clip with speech + "background music" in Avoid; our music only as its own node in the Video Editor; a clip with speech that still has music is rerun |
| Whole graph in one Section, uploads at the end | One Section per stage, left to right, uploads next to the node they feed (`lyra-workflow-layout`) |
| Clips out of order in the Video Editor | Connect in playback order; after results check and set `startMs` |
| Price guessed | Reference A rates in the plan, node `credits` before the run |
| Too many references "because the model allows it" | Small, purposeful set; video/audio refs only on request |
| Captions added without asking, too big, or over a face | Ask in the approval message; `lyra-video-editor` → Captions: size 80, y = 1440 (75%), under the face |
| A 1-minute clip promised | Hard limit; two halves or split, joined in Video Editor |
| Same prompt rerun after a failure | Change the prompt, reference or model; after two fails rewrite the scene |
## Quality gates
After each intermediate stage Claude sends the stage checklist (the final result is checked by `lyra-result-check`) and asks the user what they like and what they don't (Reference H has the full slop list):
- **Stage 1 (images):** same person in every keyframe · hands and phone natural · screen exactly like the screenshot · style right (phone-real for UGC) · nothing plastic or over-glossy.
- **Stage 2 (clips):** no music inside any clip where someone speaks (ask the user to listen, Claude can't hear) · face and outfit stable within and across clips · no morphing, flicker, warped hands · natural motion · UI correct while tapping · ends on the planned frame.
- **Stage 3 (final):** hook in 1.5–3 s · scenes in order, CTA at the end · voiceover not rushed, ends before the video, app name pronounced right · under speech only our music from the Video Editor, instrumental, trimmed with a fade · 9:16, planned resolution (720p by default), planned length · captions (only if the user said yes) size 80, at 75% of the height, never over a face (`lyra-video-editor` → Captions) · other text inside the safe zone.
Pass = the user is happy with every point that applies. Fix only what fails, within the agreed budget, with its credits.
---
# Reference library
## A. Models, prices and settings
Always call `list_node_configs` first: it is the live source of models, durations, resolutions and limits.
**How to offer a model.** Recommend **Seedance 2.5** (real people) or **Seedance 2.0** (illustration, stylized, UI/UX). Say plainly: "This is the more expensive option, but it gives the best quality for this video." Give the cost in the plan (Credit prices below). Always ask which model the user prefers before building (in the plan, step 2–3). Seedance 2.5 and 2.0 always come before any Kling. **UGC and real people talking: always Seedance 2.5, never Kling or Veo**; if the user wants cheaper, say the quality on faces and speech will drop and let them decide.
**Cheaper ladder** (one step at a time, show the new price, skip models bad at the task): Seedance 2.5 / 2.0 → Veo 3.1 (only clips ≤8 s) → Kling 4.0 (only once it is in Lyra's list) → Kling 3.0 Pro → Kling 3.0 Standard → Veo 3.1 Fast → Seedance 1.5 Pro (short lip-sync only) → Seedance 2.0 Fast → Kling 2.6 → Kling 2.5 Turbo Pro → Veo 3.1 Lite / Seedance 2.0 Mini. Drafts first, final later: test ideas on a draft model, rerun only the winner on the recommended one.
**Task → model:** real people, UGC → Seedance 2.5 · illustration, cartoon, UI/UX, moving text → Seedance 2.0 · product / nature realism, ≤8 s → Veo 3.1 · exact first + last frame, complex multi-shot → Kling 3.0 Pro · motion transfer → Kling 3.0 Motion Control Pro (Standard cheaper) · same character with video and voice refs → Kling Video 3.0 Omni · short lip-sync with synced audio → Seedance 1.5 Pro · campaign character consistency → Runway Gen-4.5 · strong physics → Sora 2 Pro (Sora 2 for drafts) · edit an existing video by chat → Gemini Omni · talking head (face + audio) → veed/fabric-1.0 (720p).
**Model cards (Lyra, Oct 2026)**
- **Seedance 2.5** (flagship, real people): 4–30 s or `adaptive` (fits length to the dialogue/script); the only Lyra model up to 30 s. **References only: never first/last frame (the fields exist but error out).** Technical max 30 images / 10 videos / 10 audio, never pushed (see reference policy). Refs are named [Image1], [Image2]… in the prompt. Default 720p (our default too; 1080p only on the user's choice). Angle and details can shift.
- **Seedance 2.0** (illustration, UI/UX): 4–15 s, `-1` = intelligent duration. Image as **frame** (start/end; picture kept exactly) or **reference** (looser), never both in one node. Rule: image with UI or any text → frame; no text and exactness not important → reference; unsure → ask. Technical max (per list_node_configs) 9 image / 3 video / 3 audio refs, never pushed. Default 720p (ours too; 1080p on the user's choice). Fast and Mini: cheaper, max 720p, drafts.
- **Veo 3.1:** 4/6/8 s (max 8), references (≤3) like the others, 9:16 default. Best realism, product, nature. Used rarely, only very short clips. Fast / Lite: cheaper, frames only.
- **Kling 3.0 Pro / Standard:** 3–15 s, first frame and/or last frame only, no references. Multi-shot, complex scenes, cartoon/stylized; weaker than Seedance on faces and human motion; cheaper than Seedance.
- **Kling 3.0 Motion Control Pro / Standard:** image + reference video 3–30 s (`character_orientation: video` up to 30 s, `image` up to 10 s). References with clear hands, head and body; avoid complex angles and blocked limbs.
- **Kling Video 3.0 Omni:** up to 7 reference images (4 with a video ref), first/last frame, 3–15 s; native audio can't be combined with a reference video.
- **Kling 2.6:** 5/10 s, first frame, native audio. **Kling 2.5 Turbo Pro:** 5/10 s, fast, cheap, no audio. **Seedance 1.5 Pro:** 5/10 s, lip-sync, dialogue.
- **Sora 2 / 2 Pro:** 4/8/12 s, first frame only. **Runway Gen-4.5:** 5/10 s, first frame.
- **Kling 4.0** (launched 16 Oct 2026): 3–30 s, up to 10 keyframes, stereo audio, cheaper than Seedance. Not in Lyra yet; offer only when list_node_configs shows it, and never ahead of Seedance for people.
- **Images:** Nano Banana Pro for finals (text, UI, people, realism, sharp), Nano Banana 2 for drafts.
**Settings in the Video Generation node:** model → seconds (or adaptive) → aspect ratio 9:16 (confirm) → quality **720p by default** (offer 1080p in the quiz: sharper faces and details, ≈ 2.4× the price) → sound **on** → how images connect (frame or reference, by model).
**Reference policy.** Limits are a technical maximum, not a target: many extras make the model unpredictable. Never tell the user how many references a model takes or suggest adding many. Default references = the images you generated (character, keyframe, product, UI). Write the montage yourself in the script; a video reference only when the user asks or the brief requires copying an edit (it works only as an editing reference). An audio reference only when the user brings a track (the video is fitted to it).
**Longer than a model allows (e.g. 1 minute).** Say honestly no model makes it in one clip (30 s Seedance 2.5, 15 s others, 8 s Veo). Offer: (A) two 30 s videos from the same idea and image, joined in the Video Editor; or (B) the full 60 s script split into two 30 s parts (check each part's length), the same reference(s) or a few style references for both, two videos in one style, joined in the Video Editor. Same model, character, style anchor, voice and music in both halves. Always tell the user first that this is possible and how.
**Credit prices** (Lyra, Oct 2026; credits per run, rounded up; a node's `credits` in `get_workflow` is always the final word):
| Node | Price |
|---|---|
| Seedance 2.5 | 720p: 28.5 per second · 1080p: 67.5 per second · `adaptive` counts as 30 s |
| Seedance 2.0 | 720p: 27 per second · 1080p: 67.5 per second |
| Seedance 2.0 Fast | 720p: 22.5 per second |
| Kling 3.0 Pro / Standard | 50.4 / 37.8 per second |
| Kling 3.0 Motion Control | ≈ 54 per second |
| Kling 2.5 Turbo Pro | ≈ 10.5 per second |
| Veo 3.1 | 1080p: ≈ 60 per second |
| Nano Banana Pro 2K / Nano Banana 2 1K | 23 / 11 per image |
| GPT Image 2 / Ideogram 3.0 Turbo | 20 / 5 per image |
| Music (ElevenLabs) | 1.25 per second of the track |
| Voiceover · AI text node | ≈ 2 · 1 |
| Video Editor, uploads, notes | 0 |
Count multiplies the price; ratio, sound on or off and frames vs references don't change it. Example (default build): character 23 + phone shot 23 + 15 s Seedance 2.5 720p 428 + 20 s music 25 + VO 2 ≈ **500 credits** (at 1080p the clip is 1 013, total ≈ 1 090). Models or settings not in the table: build, read the node, then tell the user.
**Text nodes.** Claude writes brief, script, voiceover script and music brief itself into user text nodes (the AI text nodes can't be created with the tools). Exception: **Creative Analysis** (`pattern_import`): when the user brings a reference video and the node is available, use Upload Video → Creative Analysis and write the script from its output.
**Video Editor and captions → `lyra-video-editor`.** The Video Editor is the `video_composer` node (0 credits). Assembly (order, trims, layers), the mix (VO, music volume, trim, fade-out, clip sound), the end card, on-screen text, captions (ask first; size 80, 75% of the height, word check), speed, freeze frame, effects, transitions, safe zones, export, the pre-render check, the render and the 59 / 30 / 15 s cutdowns all live in `lyra-video-editor`; follow it for stage 3.
## B. Brief, script and scenes
**Brief header:** app · platform · aspect ratio · length · language · voiceover · music · audience (Brand Kit).
**Hypothesis:** "We believe [audience] will [action] because [concept] addresses [pain] through [mechanism]" (a whole concept, not one variable).
**Then:** angle (≤100 chars) · summary (≤200) · hook mechanism · hook line (≤80; on-screen version ≤40) · value proposition (≤150) · proof point (Brand Kit or user only) · tone · offer · CTA (≤30) · format · image style · palette · must include / exclude · reference notes.
**Competitor references:** keep the idea (concept, structure, hook, format); never their logo, colors, visuals or text.
**Claims:** never invented, pricing included: no price, discount or offer that isn't listed in the Brand Kit or given by the user. AI people are never presented as real customers; testimonials only from real reviews. No body before/after for health or weight-loss apps. **Brand safety** (Lyra's System Preamble): nothing that could damage the advertiser's reputation; no profanity, no political statements, no unsubstantiated health claims, no competitor disparagement. The Brand Kit's **forbidden claims are enforced absolutely**: never in a line, a caption, a visual or the VO; if the user asks for one, say once that it is on the kit's forbidden list and leave it out unless the user confirms the kit is outdated.
**Structures:** problem → agitate → demo → CTA (default) · hook → solution → social proof → CTA · POV / relatable moment → app as the fix → CTA · before/after of the situation · single continuous shot. Scene types: hook, problem, solution, social proof, offer, cta, logo end card. Brand only at the end.
**Scene fields:** number + type · duration · visual direction (like an image brief: subject, setting, framing, angle, light, palette, mood, style, texture; no text; style per brief) · motion (one main action) · VO line · on-screen text ≤40 chars with position and animation, **marked for post** · music/SFX cue · transition · consistency (source scene, must match, allowed to change) · asset (screenshot, logo) · generation note · end state. Mark the hook scenes; give them the most detail.
**Timing:** scene durations add up exactly to the total. A beat on screen is 1.5–5 s; a clip is generated at a length the model allows and trimmed in the Video Editor. UI clips ~4 s. Hook within ~1.5 s (Reels/TikTok) to 3 s (Feed). 5 s clip beats: 0–1 establish · 1–3 action · 3–4 peak · 4–5 resolve.
**Montage:** written by Claude in the script (shots, order, length, cuts). Default: the shots live inside one clip with explicit "cut to" markers. Separate clips joined in the Video Editor only for the reasons in Step 2 (over 30 s, UI insert, different models or frames, a failed shot, the user asks).
**Keyframe:** the frame that starts the scene (start of the motion when used as first frame; the peak goes in as last frame on frame models). Generated at the video's ratio.
## C. Audio: voiceover and music
**Voiceover.** Write it yourself (from the script and Brand Kit) into a "VO script" text node, then an audio voiceover node (`elevenlabs/v4`, Lyra's recommended voiceover model; `elevenlabs/v3` also listed; voice from `list_voices`).
- Exact spoken words only: no scene labels, timestamps, "Hook:", "VO:", "[pause]", "(upbeat)", brackets, asterisks, slashes, markdown, separator dashes. Allowed: comma, period, ellipsis, ?, !. Pause = comma or ellipsis.
- One continuous text joining the per-scene lines; rhythm shows the pace; the words carry the tone (never describe it).
- No invented claims. The user's direction wins (tone, length, focus, language, style).
- **Pace (English):** 2.5 words/s conversational (default), 3.0 fast/energetic, 2.0 slow/emotional.
- **Always ~1 s shorter than the video** (15 s video → 14 s VO ≈ 35 words, calm, not rushed). Check the real audio length after generating. Too long → cut words or a faster voice; never regenerate the video for the voiceover.
- **Voice:** filter by language, accent, gender, age, use case; pick by the voice description to fit the audience and tone; play a sample; reuse the same saved voice across a campaign.
- **Languages:** same script, new VO script "Speak in <language>" + its own voiceover node with a voice in that language; run in parallel; match each in the Video Editor; check each language's length (translations run longer).
**Music.** Write the music brief from the script's mood; music node `elevenlabs/music` by default (Lyria 3 / Lyria 3 Pro if asked).
- Prompt: genre, era, BPM, key/mood shift, instruments, sync points (hit on the hook, lift on the reveal, resolve on the CTA), hook in the first 2 s, fade-out. Example: "Dark-to-hopeful cinematic electronic underscore, 110 BPM, D minor shifting to F major at the CTA; pulsing synth bass, metallic percussion, risers and impacts on the press, resolving into clean uplifting synth chords. Instrumental only, polished modern mix, smooth 1 s fade-out."
- **Anyone speaks in the video → instrumental only, no vocals, no singing, no humming.** Keep `force_instrumental` on.
- **Length = video + ~5 s** (10 s video → 15 s track, `music_length_ms`), trimmed in the Video Editor, because the fade starts early.
- **No artist names** (they can error). Check the script too.
**No music in a clip where someone speaks (fixed rule).** Video models, Seedance above all, add their own background music when the prompt leaves room: some clips get it, some don't, and every clip gets a different track. When a person speaks on camera that music is baked into the voice: it can't be removed or muted without losing the dialogue, and under our score it becomes two tracks playing at once. So:
- **Every clip with speech** (dialogue, a person talking to camera, a line in the clip, an in-clip narrator) gets this sound line: "Sound: dialogue and the natural sounds of the scene only (room tone, steps, a door, a cup on the table); no music, no background music, no soundtrack, no score, no song, no humming". And "background music, soundtrack" in its Avoid line.
- **Clips without speech:** no ban needed. If the generator adds music, that's fine: in the Video Editor the clip's sound can simply be muted and our music laid instead. With a separate voiceover and nobody speaking on camera, write "no speech, no voice".
- **Allowed in a clip with speech:** the voices, the sounds of the action (a door opening, steps, a phone buzz, a kettle, a crash), room tone and ambience. Not allowed: any music, song, humming or jingle under the voice.
- **Our music is its own music node** (instrumental when anyone speaks), on its own track in the Video Editor, under the dialogue.
- **Sound stays on at generation** (the voices and scene sounds are needed), so the prompt is the only guard. After the clips run, ask the user to listen for music inside the clips where someone speaks. Such a clip that came back with music anyway is rerun with the same sound line (its credits in the same message): muting it would mute the voice too.
**Mix in the Video Editor:** `lyra-video-editor` → Audio (voice first, music under speech, trim and fade, which clips are muted).
## D. App UI in the video
- Use as little UI in video as possible; **never invent UI**. Seedance 2.5 / 2.0 often break UI in long busy clips.
- If the screen is needed, ask: "Please send screenshots of the app screens you want in the ad." Screenshots only, never a screen recording. No screenshots → screen dark, blurred or turned away.
- **Phone image:** a second image node: "the same character holds the phone close to camera, screen facing us"; connect the main character image and the user's screenshot. Run it, then ask the user: "Is the UI exactly like your screenshot (layout, text, colors, logo)? Same person, hands and light?" Rerun the image before any video if not.
- **Way 1, one clip** (about 10 s, max 15 s): connect the character image and the phone image to the video node (Seedance 2.5 as references; Seedance 2.0 as frames, because there is text; Kling as first/last frame).
- **Way 2, UI insert:** if the UI came out bad but the rest is fine, make a short clip from the phone image (screen + finger tapping or scrolling, a few seconds) and lay it over the broken part in the Video Editor (layer above, trimmed to the moment). Plan Way 2 from the start when the UI moment is long or important.
- Show one key screen or "aha moment", not a full walkthrough. Ask after every UI result; fix only the broken part.
## E. Consistency between scenes
- **Anchors** defined once and repeated word for word in every prompt: character (age, face, hair, skin, outfit, accessories), environment (place, time of day, light direction and color), style (palette from the Brand Kit, grading, look, lens), product/phone (device, case, screen from the screenshot).
- Per scene: **source scene** (earliest that set the element) · **must match** · **allowed to change**.
- One image model for all keyframes, **one video model for the whole ad**, one ratio and resolution.
- **Character first, connected everywhere:** the character image is generated in stage 1 and **connected at build time as a reference to every image and video node that shows the person**, so the graph stays consistent even with "run all". If the user wants to choose between several characters, run stage 1 first; they name one and Claude pins it on every node that uses it (Step 7); the connections are already there. A text brief alone never makes images consistent. Two characters for A/B: one script, two character images, two videos.
- **By model:** Seedance 2.5 references (roles per [ImageN]); Seedance 2.0 frame for exactness / UI, reference for looser; Kling first/last frame; Omni references + video ref.
- Frames pin to the **selected** result; reconnect after regenerating a keyframe.
- **Hand-off:** write each clip's end state; the next scene starts from it; keep motion direction across cuts; match cuts, whip pans and cuts on action hide small differences.
- **When it breaks:** strengthen the reference and move the anchor earlier, shorten the prompt, reduce motion; a reference leaking light or framing → state its job or drop it; two failed tries → simplify the scene in the script.
## F. Prompt craft
**Image, nine blocks:** concept (2–3 words) → main subject and what it does → context → lighting → color and technique (palette, lens) → mood → composition (front, back, sides) → style (if you name a director, also describe the look) → visible details.
**Video formula:** SUBJECT → ACTION → CAMERA → ENVIRONMENT → LIGHT → MATERIALS → PACE → EMOTION → ENDING → CONSTRAINTS. A framework, not a template; one coherent direction, not a stack of tags.
- **Action:** one clear change of state + a few natural secondary moves. Weak: "a woman with a phone". Strong: "she glances at the notification, her eyebrows lift, and a small smile spreads as she turns the phone toward the camera."
- **Camera:** a move for a reason: static (control), slow push-in (intimacy), pull-out (scale), tracking (follow), orbit, pan, tilt, crane, handheld (UGC presence), whip pan (energy), rack focus. Subject motion and camera motion stated separately.
- **Framing:** eye level (natural), low (power), high (distance), overhead (geometry), three-quarter (volume), profile (silhouette); shot size; subject placement in the central 65% of 9:16.
- **Light:** one main approach + 1–2 supporting (soft diffused, hard directional, Rembrandt, backlight, rim, golden hour, blue hour, volumetric).
- **Palette:** one dominant, from the Brand Kit, kept across scenes; shift only if the shift is the story.
- **Materials:** how they react to light and motion (glass reflections stay coherent; heavy fabric doesn't float).
- **Physics:** cause and result (fabric settles, hair follows the head, a thumb really presses the screen).
- **Pace:** slow deliberate, fluid, sharp, energetic, weightless; matched to the scene.
- **Lens and focus:** 24mm wide, 35mm environmental, 50mm natural, 85mm tight, macro; say what is sharp at each key moment. Guidance, not guarantees.
- **Finish:** clean digital (precise detail, natural skin) or analog (fine grain, halation); UGC = phone camera, natural light, slight handheld.
- **Ending:** plan the final frame (eye contact, product centered, phone to camera, brief hold).
- **Image-to-video:** bring the image to life, don't replace it; preserve composition, face, outfit, light; limited movement (blink, breath, gaze, small head turn, restrained push-in); "no new objects, no scene transition, no wardrobe changes".
- **Rules:** one scene one idea · action beats adjectives · camera move needs a reason · complexity fits duration · light interacts with materials · no conflicting styles · constraints short and prioritized · clarity beats length · plan the final frame · consistency before spectacle when identity, product or UI matter.
- **Phrase bank:** smooth: "fluid motion, slow deliberate movement, graceful follow-through" · identity: "preserved facial features, consistent wardrobe, stable character appearance" · realism: "natural inertia, believable body mechanics" · product: "precision product cinematography, controlled reflections, macro detail" · light: "soft directional lighting, subtle rim light" · UGC: "shot on phone front camera, natural window light, slight handheld wobble, casual, unpolished" · ending: "controlled final pose, brief visual hold".
- **Pre-generation check:** subject clear · identity preserved where needed · main action explicit · camera defined · composition and location fit · light and palette coherent · hands, hair, objects plausible · pace fits duration · final frame intentional · key unwanted changes constrained · settings match the model · nothing contradictory.
## G. Errors
| Problem | Fix |
|---|---|
| Seedance 2.5 errors with an image | It was a frame → reconnect as reference |
| Seedance rejects inputs | Frames and references mixed → pick one |
| Video ignores the script or image | Connect both to the video node |
| Video stays on the old image | Keyframe regenerated → reconnect it |
| Duration rejected | Use a listed value (model first, then seconds) |
| User wants 1080p | Set `resolution: 1080p` (Seedance 2.5 / 2.0); 2.0 Fast / Mini can't do 1080p |
| Music node error | Artist name → describe genre, tempo, mood |
| Vocals under the voice | Instrumental only, force_instrumental on |
| Music fades early | Generate ~5 s longer, trim |
| Voiceover too long | Shorten to (video − 1 s) or faster voice |
| Clip audio clashes | Clip without speech: mute/lower in Video Editor |
| Music inside a clip with speech | Can't be removed: rerun the clip with the no-music sound line (Reference C) |
| Clips in wrong order | Disconnect and reconnect in playback order |
| UI garbled | Phone image + UI insert (D) |
| Face drifts | E → "When it breaks" |
| Text appears in video | Remove it from the prompt; text goes on in the Video Editor |
| Longer than the model allows | Two halves or split script (A) |
| Kling 4.0 asked for | Not in Lyra yet; offer Seedance 2.5 |
| Two failed tries | Rewrite the scene in the script; if the image confuses the model, use it as a reference instead of a frame (where allowed); never rerun unchanged |
## H. De-slop
**Prevent:** style from the brief (UGC phone-real, not "premium cinematic") · real skin ("natural skin texture, visible pores"), never "flawless" · lived-in places with 2–3 specific details · no "stunning, 8K, masterpiece, hyper-realistic" · simple hand actions, one object in hand, hands visibly touching · faces frontal or three-quarter, one person in focus · one action, one camera move, physical cause and result · no generated text, UI or logos · a short constraints line. Images: "text overlays, captions, watermark, blurry, low quality, distorted faces, extra limbs". Video: "text generation, on-screen captions, morphing faces, identity drift, outfit change, flickering, jitter, warped hands, unstable geometry, sudden camera jumps" + 1–3 scene risks. If the model has no negative field, put a short "Avoid …" line at the end of the prompt.
**Slop signs:** faces (plastic skin, identity change, morphing, dead eyes) · hands (extra or merged fingers, passing through objects, floating phone) · motion (rubber limbs, sliding feet, floaty movement, jitter) · text/UI (garbled letters, invented or changing screens, warped logo) · scene (flicker, objects popping, melting background, warped lines) · look (over-glossy, over-saturated, stock vibe, wrong style) · audio (robotic or rushed voice, wrong app name, VO over the video, vocals under speech, abrupt music end) · edit (mismatched cuts, wrong order, CTA cut off, text outside the safe zone).
## I. Brand Kit
Every brief, script, prompt, voice and music direction is built on the Brand Kit: audience first, then product, value, tone, colors, claims, forbidden claims (enforced absolutely), must include / exclude. Source order: the chat → the kit connected to the workspace / workflow → ask (send it, or check and connect one of the workspace's kits). The user's chat request always wins; the kit fills everything they didn't say; mention a conflict in one line.
## J. App ads on Meta (what works)
- Vertical 9:16 video first (Reels and Stories carry most app-install volume); 15–30 s; a hook that shows the app working, not a logo.
- 3–5 hook variants per concept; test one variable at a time; 2–3 new concepts a month (creatives fatigue in days to weeks); Advantage+ app campaigns need several different concepts.
- Formats that convert: UGC style (phone-shot, person to camera) beats polished brand video on cold traffic · problem → agitate → demo → CTA ending on the key screen · real people using the app · one simple key screen, not a walkthrough · before/after of the situation · specific, plausible social proof from the Brand Kit.
- Hook in ~1.5 s (Reels/TikTok), by 3 s (Feed); no dead air; no logo intro. Hook rate (3-s views ÷ impressions) >30% good, <20% weak.
- Length: Reels 6–30 s (15–20 s safe), Stories 6–15 s, Feed 15–30 s (4:5 or 1:1 as a later variant).
- Sound off: most viewers watch muted → recommend captions for all speech when asking the user (`lyra-video-editor` → Captions: ask first), key message also on screen, same words as the VO; high-contrast, one consistent place, size 80, at 75% of the height under the faces; added in the Video Editor.
- Safe zone: faces, the subject and headline text in the central 65% of 9:16, away from the top bar and the bottom CTA area. Captions are the exception: at 75% of the height, under the faces (`lyra-video-editor` → Captions).
- CTA: a concrete offer ("Try free for 7 days") beats "Download now"; in VO and on screen in the last 2–3 s.
- Judge creatives by trials, payers and day-7 retention, not only cost per install; give a test 2–3 weeks.
lyra-video-editor29.8 KB
View saved version →
---
name: lyra-video-editor
description: "Lyra Video Editor: assembly, mix, end card, text, captions (asked first, size 80, 75% height), pacing, keywords, SFX, render check, and 59/30/15 s cutdowns. The assembly stage of every Lyra video skill."
---
# lyra-video-editor
The assembly and finishing skill for every Lyra video. The video skills (`lyra-video-ad-generation`, UGC, hooks, UI motion, short drama, copy competitor, variations, concept multiplier, fix) make the pieces: clips, voiceover, music, end card. This skill puts them together in the Video Editor. It mixes the sound, adds text, captions and SFX, sets the pace, renders, checks the render and cuts the short versions.
Use for "edit / assemble the video", "stitch the clips", "add captions / subtitles", "music quieter", "fade the music", "add an end card", "make it more dynamic", "add a sound effect", "cut a 30 s / 15 s version", "make cutdowns", "Remotion render failed", or as the assembly stage of every Lyra video skill.
**This file is the only source for the Video Editor and captions.** Every other Lyra skill points here for them.
**Core rules come from the base skill.** Part 1 of `lyra-video-ad-generation` holds the shared steps: one approval message, pre-run check, credits, picking a result, links, variations, open canvas, runtime failures. Canvas changes (new Video Editor nodes for cutdowns, a "Final" section) follow `lyra-workflow-layout`.
**When it runs.**
- **As stage 3 of a video skill.** The video skill's plan already has the Video Editor node, and its approval message already carries the captions question (with the style choice, Captions below). Run this file from Step 2.
- **On its own.** The user asks to edit, assemble, add captions, change the music, add an end card, make it more dynamic or cut short versions of an existing video. Start at Step 1.
---
## The Video Editor in Lyra (checked in Lyra, Oct 2026)
- **Node:** `video_composer` (`create_video_composer_node`), label "Final: …". **0 credits.** Lyra renders it with Remotion; a render takes ~20 to 40 s.
- **The edit lives in `video_rendering_composition`**, read with `get_workflow`, written with `update_node`. **The whole edit can be built by the tools, without opening the editor:** a composition sent with `update_node` renders as is, even with no node connected. Always read the whole composition first, change only what's needed, send it back whole, then `get_workflow` to check it held.
- **Opening the editor in the UI** (Claude's browser or the user) is needed only for what the tools can't do: the **Captions** button (transcription). Everything else is a composition field.
### Composition fields (as Lyra saves them)
```
canvas: { fps: 24, width: 1080, height: 1920, durationMs }
safeZone: "instagramReels" | … (editor guide only, not rendered)
tracks: [
{ kind: "video", name, locked, visible, clips: [
{ id, kind: "video", assetUrl, sourceNodeId, sourceResultUuid, sourceDurationMs,
startMs, durationMs, trim: { sourceStartMs, sourceEndMs }, volume,
position: { x, y, width, height }, // zoom / crop / split screen
speed: 2, // 0.25 to 4
freezeAtMs: 3052.5, // freeze frame: its own clip, trim start = end
transitionOut: { kind: "whipLeft", durationMs: 450 } } ] },
{ kind: "audio", name: "Music" | "Voiceover" | "Audio", role: "music", volume, muted, sourceNodeId, clips: [
{ id, kind: "audio", assetUrl, startMs, durationMs, trim, volume, sourceNodeId, sourceResultUuid } ] },
{ kind: "text", name, clips: [
{ id, kind: "text", content, startMs, durationMs, position: { x, y }, align: "center",
font: { family: "Inter", sizePx: 75, weightPx: 800 }, color: "#1f2937",
style: { presetId, strokeColor, strokeWidthEm, backgroundColor },
effects: [ { id, kind: "popIn" } ] } ] },
{ kind: "caption", name: "Captions", font: { family, sizePx }, styleId: "outline",
animation: { kind: "activeWordColor" }, highlightColor: "#8FB8FF",
position: { x: 540, y: 1440 }, sourceCaptionUuid,
clips: [ { id, kind: "caption", startMs, durationMs,
words: [ { text, startMs, endMs } ] } ] }
]
```
Field values seen so far: transition `whipLeft`; effect `popIn`; caption styles `outline` (white text with an outline, no box) and `blackBox` (a box), caption animations `activeWordColor` (the spoken word changes colour, no box) and `activeWordHighlight` (a coloured box behind the spoken word), `highlightColor` on the caption track (Lyra's default is yellow `#FDE047`); text preset `karaoke`. For any other kind or preset, set it once in the editor UI and read back the name Lyra saves. Never invent a value.
### What the editor offers (UI names)
- **Speed** 0.25× to 4× (slider, presets). The clip's length follows; the clips after it shift.
- **Freeze**: holds the frame under the playhead for 2 s; drag its edge to lengthen it.
- **Layers** (on the timeline labels): mute (audio only), hide, lock, delete, rename (double-click), reorder (drag or arrows); **+ Layer** adds an empty track. The top layer is in front. Audio layers are named after their source (Music, Voiceover, Audio); each music result gets its own layer.
- **Sources** dropdown: every connected input, with a count; a source already in use can't be added twice.
- **Effects** (Effects tab, preview cards): Motion / Camera (shake, bounce, float…), Entrance (fade, slide, scale / zoom, pop, bounce, blur, spin, drop in), Exit (the same out), Reveal (typewriter, word by word, line by line, wipe, mask), Attention (pulse, flash, glow, RGB split, glitch, blur…). Each has a duration; some have start time, intensity, direction and colour.
- **Transitions** (19): fade, fade to black, cross dissolve, dip to white, slide left / right / up / down, push, zoom in, zoom out, pull in, whip pan left / right, blur, flash, glitch, spin, swipe / wipe. Length 0.25, 0.5 or 1 s. A transition belongs to the right edge of the clip on its left and overlaps the two clips. It also works across tracks and gaps. Not on a locked layer. The old node field `transition_effect` is not used by the timeline: use `transitionOut`.
- **Text**: the same styles as captions, plus outline, shadow, background, caps, italic, letter spacing; 12 extra fonts; default size 75.
- **Captions**: Captions button, style presets (about 26), animations (style default, active word highlight, active word pop, karaoke highlight, word by word, phrase by phrase, active word bounce, active word colour), highlight colour, an Edit tab to fix the words.
- **Canvas**: resolution 480p to 4K, framing Fit / Fill / Zoom.
- **Safe zones**: TikTok, Instagram Reels, Instagram Stories, YouTube Shorts guides, saved per node, not rendered. The Reels guide in Lyra marks the clear area at about 14% to 65% of the height.
- **Results** (left of Render): past renders; opens by itself when a render finishes.
### Known behaviour (check every time)
| Behaviour | What to do |
|---|---|
| **A variation plus an opened editor gives an empty edit.** In a new variation the results get new ids, and opening the editor deletes every track while marking the sources as added, so nothing comes back. The render then fails ("Remotion render failed") or is empty | After `create_variation`, read the Video Editor's composition. If its tracks are empty or point to old results, rebuild it with `update_node`: the same clips, each with its `sourceNodeId` and the variation's own `sourceResultUuid` (the ids now listed in `absorbedSourceNodeIds`). Say it in one line. |
| **An empty edit doesn't render** ("Remotion render failed"): no clips on the tracks, inputs without results, lost connections | Never run it empty. Pre-render check below. |
| **A black tail after speed, transitions or trims.** Clips get shorter; `canvas.durationMs` doesn't always follow, and the render ends on black | Set `canvas.durationMs` = the end of the last clip (startMs + durationMs), in whole seconds where possible. Check the last frame of the render. |
| **A clip is pinned to one result** (`sourceResultUuid`, `assetUrl`). After a clip is rerun or another result is picked, the edit still plays the old one | After any rerun, compare each clip's `assetUrl` with the result you want (`get_run_results`) and update it. |
| **A node connected after the edit exists isn't added.** The editor adds new inputs only when it is opened | Add the clip (a new VO, music, insert) to the composition yourself with its `assetUrl`, `sourceNodeId`, `sourceResultUuid`. |
| **A deleted clip comes back** while its node is still connected | To drop a source for good, also `disconnect_nodes` on the canvas. |
| **Edit Video is disabled** when no video node is connected | Connect at least one video node, or build the edit by the tools. |
| **Captions on a video without speech** stay "Parsing…" forever. **With speech** they take about a minute | Captions only on speech; wait up to ~90 s; no track after that → tell the user. |
| **Whispered or quiet speech is transcribed in part** (whole lines missing) | Word check against the script, always (Captions below). |
| **The editor may cut clips to 5 s on opening** (reported, not reproduced) | After any opening of the editor, read the composition and restore clip lengths and trims. |
| **An open canvas or editor tab writes its old state over tool edits** | Before `update_node`, the workflow tab (the user's and Claude's) is moved off the workflow; reopen it after to show the result. |
| **Black preview at 00:00** in the editor | A preview bug, not the render. |
---
## Step 1. Read what's there
1. `get_workflow`: the Video Editor node(s), their inputs and each input's selected result. No Video Editor yet → `create_video_composer_node`, label "Final: {length}", in the "Final" section on the right (`lyra-workflow-layout`), inputs connected in playback order. **Every new Video Editor gets its own rose section and STEP note right away**, by `lyra-workflow-layout`, also when Claude only came to edit. In the user's own workflow nothing else is moved or renamed without a yes: add the editor's section, then offer the full tidy-up in one line (sections, STEP notes, "(copy)" labels, stray nodes).
2. Read the composition. Empty or stale (variation, rerun) → rebuild it (Known behaviour). **No composition yet and the clips were made in another chat** (so `get_run_results` can't give their file links): open the Video Editor once in the browser; it imports the connected clips with their `assetUrl`, `sourceResultUuid` and real lengths. Do the Captions step in the same opening if captions are wanted, then close it and work by the tools.
3. From the script, collect: playback order, each scene's start and end second inside each clip (cut points), the VO text and length, the music length, the end card, the on-screen text lines (marked for post), the keywords, the CTA.
4. A missing result (a clip still running or failed) → finish or fix that node first (`lyra-fix`); never edit around a gap.
## Step 2. Plan the edit
A short timeline, readable in under a minute:
| Time | Video | Above | Sound |
|---|---|---|---|
| 0–3 s | Clip 1, 0–3 s (hook), punch-in at 1.5 s | Text "POV: 2 am, brain won't stop" (pop in) | VO from 0.3 s · music 0.15 |
| 3–11 s | Clip 1, 3–11 s, punch-in at 6 s | UI insert 6–9 s · keyword "1 minute" at 7.2 s | VO · music 0.15 |
| 11–13 s | Clip 1, 11–13 s | — | VO ends 13.8 s |
| 13–15 s | End card 2 s | — | music resolves, fade-out 1 s |
Plus one line each: captions (yes / no; no box, the highlight colour and where it comes from), transitions (cuts by default), resolution and framing (1080p, Fill), cutdowns if asked.
**Approval.** The editor is free, so a plan with only edits runs straight after it. Captions yes / no is always the user's choice, asked once (Captions below). New paid nodes (a short VO or music for a cutdown) go into one message with their credits (base Steps 3 and 6).
## Step 3. Build the edit
1. **Composition by the tools** (`update_node`): order, trims, splits for punch-ins, speed, freeze, transitions, text and keyword clips, audio tracks (and SFX only if asked), volumes, mute, canvas length.
2. **Captions** (only if the user said yes): the one UI step. Open the Video Editor in Claude's browser, press Captions, wait for the words (up to ~90 s), apply the house style (outline, active word colour) or the box the user asked for, set the highlight colour from the video or Brand Kit, set size 80, leave the editor (or set `styleId`, `animation`, `highlightColor` by the tools afterwards). **Captions are timed to the source clip.** When the edit cuts or moves the clips, shift every caption clip and word by the same offset as the clip it sits on (`startMs` and each word's `startMs` / `endMs`), and drop the words that fall in cut-out parts. Then read the composition again: set `position {540, 1440}` on the caption track (there is no height field in the UI), restore any clip lengths that changed, `update_node`, `get_workflow`. Without a browser, ask the user to press Captions and say when the track is there; then set the rest by the tools.
3. Pre-render check, render, edit check, then `lyra-result-check` (Steps 4 to 6).
### Video: order, trims, pace
- **Order:** clips in the script's order; `startMs` of each = the end of the one before. No gaps or black frames unless planned.
- **Trims:** `trim.sourceStartMs / sourceEndMs` to the planned seconds; `durationMs` = the trimmed length (÷ speed). Cut on action, at a scene boundary or at the end of a spoken line, never mid-word.
- **Pace (default for ads):** the picture changes every **2 to 3 s**. A change is any of: a cut inside the clip, a punch-in, a text or keyword pop, a UI insert or B-roll, a transition. In the **7 to 10 s** window put one stronger interrupt (a punch-in plus a keyword, a new angle, the app moment): viewers decide around then whether to stay. For Google App campaigns, at least two changes in the first 5 s. A slow, calm concept (ASMR, meditation, luxury) keeps its slow pace; follow the concept, say it in the plan.
- **Punch-in zoom (cheap cut without a new generation):** split the clip into two clips with the same `assetUrl` (the first trimmed to the cut point, the second starting there) and give the second a larger `position`, centered on the face or the subject: scale 1.15 to 1.3 (scale around the face point P = (px, py) from the clip's current `position`: width × s, height × s, x = px − s × (px − x), y = py − s × (py − y); e.g. s 1.25 on a face at (540, 620) gives x −135, y ≈ −165, 1350 × 2421). Alternate normal and punched-in on a talking head. Not when the zoom would crop the hands, the phone screen or the text in the frame.
- **Layers:** the main video at the bottom; UI inserts, logo, B-roll, text above, trimmed to their moment. A UI insert covers the broken screen moment exactly (base Reference D). Split screen: two video clips side by side with their `position` (e.g. 540 × 1920 each, Fill).
- **Speed:** 1.1× to 1.5× to tighten a slow clip or land a beat, instead of a new generation. Not on clips with speech (the voice changes with it).
- **Freeze:** to hold the last frame under the CTA, or to stretch a clip short by 1 to 2 s.
- **Transitions:** hard cuts by default. A transition only between different places or times, one kind per ad, 0.25 to 0.5 s; whip pan or zoom for energy, cross dissolve for calm. Every transition shortens the total: fix `canvas.durationMs`.
- **Effects:** for a reason: an entrance on text, a slow push-in (Motion / Camera) on a still image or the end card, an attention pulse on the CTA. No effects on faces in UGC.
- **Canvas:** 1080×1920, 1080p (720p for drafts, 4K only when asked); Fill by default, Fit when a clip of another ratio must stay whole.
### Audio: voiceover, music, clip sound, SFX
- **Voice first.** VO at full volume, starting 0.2 to 0.5 s in, ending ~1 s before the video (base Reference C). Too long → shorter text or a faster voice; never stretch the video.
- **Music:** under speech 0.1 to 0.2 (default 0.15); without speech it can lead (about 0.6 to 0.8). Trimmed to the video, ending on a musical resolve, ~1 s fade-out on the last frame (in the editor on the music clip; no fade field seen in the composition yet). One music track per ad.
- **Clip sound:** a clip with speech keeps its sound and must have no music inside (one that has it is rerun, base Reference C); a clip without speech is muted (or ~0.2 ambience) under our music.
- **Sound effects (SFX).** Not added by default and not asked about every time. Where they come from, in this order:
1. **In the video itself (default).** Sounds of the action (a bubble pop, a phone buzz, a door, a splash, a whoosh of a fast camera move) are written into the clip's video prompt in the sound line, and Seedance generates them with the clip (sound on). The video skills do this when they write the prompts (base Reference C); the editor adds nothing.
2. **The user asks for a specific sound at the editing stage** (or a sound the clip didn't get): generate it in Lyra with an audio music node on **ElevenLabs** (`create_audio_music_generation_node`, `elevenlabs/music`). The prompt describes only the sound, e.g. "a single short soft whoosh, airy, no music, no melody, no rhythm", `force_instrumental` on, `music_length_ms` 5000 (the minimum, ≈ 7 credits). Trim it to the sound in the editor and place it on its own audio track named "SFX" at the planned moment, volume 0.3 to 0.6, never on top of a key spoken word. Its credits go in the same message as the plan.
3. **The ElevenLabs sound doesn't work for the user:** say so and ask the user to send the sound file; upload it (`create_upload` / `open_upload_widget`, `attach_upload`) and place it the same way. Never invent a link.
- Several languages: one Video Editor per language, each with its own VO and captions.
### End card
- The last **2 to 4 s** (2 s in 15 s, 3 s in 30 s and longer), whole seconds, ending exactly on `canvas.durationMs`.
- From the video skill (an end card clip or image; `lyra-ui-motion-video` makes store-style ones). Text missing from the image (price, disclaimer) is a text clip, never generated. The CTA said in the VO and shown on screen in the last 2 to 3 s. Inside the safe zone.
### On-screen text and keywords
- **Lines marked for post** in the script (hook ≤40 characters, key message, CTA). Never generated inside a clip. Hook text from frame 0 of the hook.
- **Keywords:** 1 to 3 words of the VO or dialogue that carry the message (a number, the pain, the benefit, the app name) pop up as their own text clip **right after the word is spoken**: `startMs` = the word's start + ~0.1 s (from the caption words' timing or the VO script pace), on screen 0.8 to 1.5 s, an entrance effect (pop in, scale in). 2 to 4 per 15 s ad. With captions on, pick a keyword the captions don't show at that moment, or let the caption highlight carry it: the same words twice on screen at once read as noise.
- **Placement:** inside the safe zone (about 14% to 65% of the height on Reels), never over a face, never on the caption band (captions sit at 75%): keywords and headlines in the upper half (y ≈ 300 to 900); when the face fills that band (a centered talking head), between the face and the captions (y ≈ 1100 to 1250, on the chest, never on the hands holding the phone).
- **Style:** one text preset per ad, brand fonts and colours from the Brand Kit, high contrast; size 75 to 110 for keywords, 75 for longer lines. The same colour rule as captions: a keyword box or text colour from the Brand Kit, the logo or the video (e.g. white text on the video's own dark blue), never the default yellow.
## Captions
- **Ask first, never by default.** Captions yes or no is the user's choice, in the one approval message. Recommend yes for any ad with speech (most people watch muted).
- **House style: no box.** White text with a thin outline (`styleId: "outline"`), the spoken word in colour (`animation: activeWordColor`). A box (`blackBox`, or `activeWordHighlight`, which puts a box behind the spoken word) only when the user asks for one, or when the text can't be read without it (a busy, bright background), said in the plan.
- **The colour is never Lyra's default yellow.** Set `highlightColor` (and the box colour, if there is a box) to fit the video: the Brand Kit's accent colour or the logo's colour first; no Brand Kit → a colour taken from the video itself (its key object, UI, light) or a neutral (white, light grey, a soft tint of the video's palette). Yellow only when it is the brand's or the video's own colour. It must read clearly on the frames where captions sit; check it in the edit check. Say the colour and where it comes from in the plan ("captions white, spoken word light blue from the Windows title bar").
- **Made only by the Captions button** (Step 3). Only on speech.
- **Size 80** on 1080×1920 (Lyra creates 115). Max 2 lines.
- **At 75% of the height** (the house default): caption track `position {x: 540, y: 1440}` (0.75 × height on other canvases). Lyra's own default is lower (~88%), so always set it. On close-ups this lands under the mouth, on wide shots at chest level. Never over a face or the mouth: if a face sits there, move the captions lower (y ≈ 1530, at most 1650). If the user wants them elsewhere, place them there. Don't pull them up into the red Reels frame.
- **Word check against the script, every time**, in the Edit tab or in the composition's `words`: the app name, names, numbers, punctuation, ellipses, and missing lines (whispers and quiet speech drop whole phrases). Missing words are added with their timing from the script pace.
- The first word visible from its first frame (an entrance animation can hide it).
- After any change to the VO or the clips, captions are made again and checked again.
## Step 4. Pre-render check
Right before every Video Editor run (base Step 5 plus these):
- every input has a result; each clip's `assetUrl` / `sourceResultUuid` is the result agreed (not an old one);
- the composition is not empty: a video track with clips;
- clip lengths and trims as planned, none cut to 5 s; `startMs` in a row; no gaps or overlaps except transitions;
- `canvas.durationMs` = the end of the last clip; no black tail;
- VO ends ~1 s before the end; music trimmed, at its volume, fade on the last frame; clips without speech muted, clips with speech not; any SFX not on key words;
- picture changes every 2 to 3 s (unless the concept is slow), an interrupt at 7 to 10 s;
- captions as answered: no box (unless asked), highlight colour from the Brand Kit or the video (not the default yellow), size 80, `position` y 1440, words checked;
- text, keywords and end card inside the safe zone, off faces and off the caption band;
- 1080×1920, 1080p, Fill / Fit as planned.
## Step 5. Render
`run_node` on the Video Editor; `get_run_results` until it is done (never run it twice while it runs). "Remotion render failed" → almost always an empty or stale composition: Pre-render check, fix, render again (free).
## Step 6. Edit check, then the full check
**Edit check (this skill, before the report).** A quick look only at what the edit itself can break, in Claude's browser signed in to Lyra: open the result `url` in its own tab, hide the controls, seek with JavaScript and look at:
- 0.1 s: the hook frame and its text;
- 0.2 s before the end: no black tail, the end card whole;
- one frame inside each caption phrase: no box (unless asked), the highlight colour readable and fitting the video, at 75%, the words right;
- each punch-in and keyword: faces still in frame, keywords off faces and off the caption band.
An edit problem found here (black tail, wrong caption place, a keyword over a face) is fixed in the composition straight away (free) and rendered again. Close the tab. No browser → skip to the full check.
**Full check → `lyra-result-check`.** Faces, hands, phone screen and logo, cuts, all text, and the measured sound (levels, music under the voice, hard stop) are checked by `lyra-result-check`, which runs automatically after every final render and goes into the final report. Don't repeat its checks here.
## Step 7. Report
Base link rules: one video → the video link + the workflow link; several (cutdowns, languages) → the workflow link and the label of each Video Editor.
> Calmly · "2 am" · final 15 s: done. Video: {url} · Workflow: https://lyra.splitmetrics.com/workflows/{uuid}. Edit: 6 picture changes, punch-ins at 1.5 and 6 s, keywords "2 am" and "1 minute", captions (no box, the spoken word in the brand's teal) at 75%, end card 2 s. Editor renders are free. (The full check from `lyra-result-check` follows in the same report.)
---
## Short versions: 59, 30 and 15 s
One finished ad gives several lengths. Make only versions shorter than the master. 59 s (not 60) fits every Meta placement; 30 s and 15 s are the main test lengths.
**How.** Each version is **its own Video Editor node** (no new video credits), label "Cut: 30 s", in the "Final" section next to the master, its composition built by the tools from the master's clips. Same variation as the master, unless the user asks for another one.
| Version | Structure | Rule |
|---|---|---|
| **59 s** | the master minus the weakest scenes: one pain or problem scene and one payoff or proof scene | hook, the app moment and the end card stay whole |
| **30 s** | hook 3 s · problem 6 to 8 s · the app / turn 8 to 10 s · result 5 to 7 s · end card 2 to 3 s | one beat per part, the strongest take of each |
| **15 s** | hook 3 s · the app or result in one beat 9 to 10 s · end card 2 s | the hook and the app in the same ad, nothing else |
- **The same hook** opens every version. A new hook is `lyra-video-hooks`, not a cutdown.
- **Cut only at scene boundaries** or at the end of a spoken line, from the script's scene times (none → write them first and check with the user).
- **Voiceover:** a VO across scenes doesn't survive cuts. Each version gets **its own short VO** on the same voice, ~1 s shorter than the version (≈ 2 credits). In-clip dialogue: cut between lines.
- **Music:** the master's track trimmed with a 1 s fade, ending on a resolve; or a short music node (version + 5 s, 1.25 credits per second) when the cut lands badly.
- **Pace, keywords and any SFX** re-placed for the version's timing; **end card** in every version; **captions** made again (Captions per Video Editor) and checked.
- Each version gets the Pre-render check, the edit check and `lyra-result-check`.
- **Plan in one message:** the versions, what each drops, the new VO / music nodes and their credits (editors are free), the captions answer. After the yes, build and render all versions.
- **Names:** the master's code with the length (`…-59cut`, `…-30cut`, `…-15cut`); node labels "Cut: 59 s", "Cut: 30 s", "Cut: 15 s".
---
## Common mistakes (Video Editor)
| Mistake | Prevention |
|---|---|
| Opens the editor in a new variation and renders an empty edit | Read the composition after `create_variation`; rebuild it by the tools |
| Runs an empty Video Editor ("Remotion render failed") | Pre-render check: clips on the tracks |
| Adds a Video Editor and leaves it outside any section, with no STEP note | Step 1: its own rose section and STEP note by `lyra-workflow-layout`; offer the tidy-up of the rest |
| A black tail at the end after speed, transitions or trims | `canvas.durationMs` = the end of the last clip; check the last frame |
| The edit plays an old take after a rerun | Update each clip's `assetUrl` / `sourceResultUuid` |
| Connects a new VO after the edit exists and expects it to appear | Add it to the composition yourself |
| Rebuilds the composition from memory, drops captions or volumes | Read the whole composition, change only the needed fields |
| Invents a transition, effect or style name | Use the names seen in Lyra, or set it once in the UI and read it back |
| Uses `transition_effect` on the node for transitions | `transitionOut` on the clip |
| Captions added without asking | Ask yes / no in the approval message |
| Captions with a box by default, or left in Lyra's yellow | No box; highlight colour from the Brand Kit, the logo or the video |
| Captions left at 115 or at Lyra's ~88% default | Size 80, `position {540, 1440}` |
| Caption words not checked (whispers drop lines, app name, punctuation) | Word check against the script every time |
| Presses Captions on a video without speech | Captions only on speech |
| A static talking head for 15 s | A change every 2 to 3 s; punch-ins; an interrupt at 7 to 10 s |
| A punch-in that crops the hands, the phone screen or the text | Pick another moment or a smaller scale |
| Keywords over a face or on the caption band | Upper half, inside the safe zone |
| Adds or asks about SFX on every ad | Action sounds go into the video prompt; editor SFX only when the user asks |
| SFX on top of a key word, or too loud | On edit points, volume 0.3 to 0.6 |
| Invents an SFX file or link | ElevenLabs music node; if it doesn't work, ask the user for the file |
| Music over the voice, ending early or stopping hard | 0.1 to 0.2 under speech, trimmed, 1 s fade |
| A clip with speech muted to kill its music | Rerun it with the no-music sound line |
| Speed on a talking clip | Avoid; the voice changes |
| Edits with the workflow open in a tab | Move the tab off first, reopen after |
| Reports a render without looking at it | Edit check (Step 6), then `lyra-result-check` |
| A 30 s cut made by cutting the master's VO mid-sentence | Its own short VO per version |
## Quality gates (final video)
**Edit check (Step 6):** no black tail, the planned length · the hook frame and its text at 0 s · captions without a box, the highlight colour from the brand or the video, size 80, at 75%, the words as in the script · punch-ins keep faces in frame · keywords off faces and off the caption band · the end card complete.
**Everything else** (faces, hands, screen, logo, cuts, text, the measured sound, and the questions to the user about pronunciation and voice) → `lyra-result-check`.
**Versions:** each cutdown keeps the hook, the app moment and the end card, with its own VO and captions.
Pass = every point that applies is fine. Fix only what fails; editor fixes are free and render again at once.
lyra-video-hooks40.5 KB
View saved version →
---
name: lyra-video-hooks
description: "Hooks for mobile app video ads in Lyra, built from the Brand Kit and the audience's real pains, then turned into finished videos for an A/B test. Use for \"hooks for my app\", \"4 hook variants\", \"write hooks / a hook bank\", \"a visual hook\", \"a catchy / brainrot hook\", \"hook multiplier\", \"test new openings on this ad\", \"the hook is weak / hook rate dropped\", \"a stronger first 3 seconds\", or a Lyra Hook template. Core video rules come from lyra-video-ad-generation."
---
# lyra-video-hooks
Mini skill. Finds the audience's pains in the Brand Kit, writes a bank of hook ideas, then turns the best 4 (3 to 6) into finished videos in Lyra.
**Canvas layout → `lyra-workflow-layout`.** Every workflow this skill builds or changes is laid out by `lyra-workflow-layout`: sections in reading order with a STEP note above each one, the team's color code, clear node labels and the final check. The layout lines in this file only say which sections this creative needs.
**This is a way of thinking, not a script.** The rules below are defaults and good practice. Use judgment: when a different hook, order or combination serves the idea better, do it and say why in one line. Only a few things are fixed: truth (no invented claims, reviews or numbers), the Brand Kit's facts, Lyra's technical limits, and the user's explicit choices.
**Base skill first.** Everything not written here follows `lyra-video-ad-generation`: the 8 steps, instruction order, app card, plan table and stages, run options with credits, run and report, prompt rules, models (Reference A), audio (C), app UI (D), consistency (E), prompt craft (F), errors (G), de-slop (H), Brand Kit (I), Meta app ads (J). This file only adds what is specific to hooks. If the two disagree, the user wins, then this file, then the base skill.
**Method.** GBP (Gut, Brain, Pocket) and the More, Better, New iteration framework. This skill is **MORE**: new Guts on the same Brain and Pocket. Hook writing follows direct response practice: audience awareness, voice of customer, one idea per hook, every claim true.
---
## How to think about a hook
**What it is.** The hook is the **Gut** of the ad: the first 1 to 3 s. It has up to four layers that fire together: **visual** (the first frame and the first movement), **verbal** (the first spoken line), **text** (the caption on frame 1), **sound** (SFX, music hit, silence). Its job: stop the scroll in about 1 s and, by 3 s, tell the right viewer "this is about your problem". Meta reads early retention from the first second, so frame 1 already has to move.
**Three kinds of hook.** Decide this first, for every idea:
| Kind | What happens in 0 to 3 s | Works best when |
|---|---|---|
| **Visual hook** | the picture does the work: an action, a surprise, a strange situation, a transformation; no one needs to speak (music, SFX, a caption) | the pain or the result can be *seen*; music-led or ASMR videos; one video for many languages; cinematic or surreal concepts |
| **Verbal hook** | a person speaks first: a pain line, a question, a confession, a callout; the picture is a face already mid-sentence | UGC and talking head; the pain is a feeling or a thought that is hard to show; the audience needs to be named |
| **Combined hook (stack)** | a short visual beat first (0 to 1 s), then the spoken line right on top of it (1 to 3 s); example: a clap in front of the camera, then the girl says the pain in the audience's words | most UGC app ads: the visual stops the thumb, the line tells the right person "this is you" |
**How to choose.** Think about the idea of the whole video, not the hook alone:
- What is the strongest thing to show or say in the first second? Lead with it.
- Can the pain be seen? Lean visual. Is it a thought or a feeling? Lean verbal, maybe with a small visual beat.
- UGC and talking head: a combined hook is usually strongest (a physical beat + a pain line). Cinematic, surreal or music-led: a visual hook alone is often enough. Reels moves fastest: keep visual tricks short and get to the person quickly.
- Two layers must tell **one** idea. A visual beat and a line that say different things fight each other; then pick one.
- One strong hook beats two weak ones stacked. Stack only when each layer adds something: the visual catches, the line qualifies. A **double hook** (a second hook at 3 to 6 s) is a separate test (Better), not the default.
- Sometimes the pain itself is the hook; sometimes the hook is a surprise and the pain comes right after. Decide per idea.
**The story the hook opens (default spine).** Hook (0 to 3 s) → **the pain**, shown on a person so the viewer recognises themselves (3 to ~6 s) → **how the app solved it**, one real feature, the change visible (~6 to 12 s) → CTA. This is the default for app ads (problem-led hooks take most app video spend). Other spines are fine when they fit: outcome first then how, demo first, old way vs new way, a story cold open. Choose what presents the idea best and say why in the plan.
**Final test for every hook:** relevance + curiosity + a reason to care. Would the right person understand it at once, recognise something from their life, and want the next seconds?
**Main character of the first seconds (3P):** **Problem** (the pain, on a person living it) · **Product** (the app in use, real screens) · **Persona** (someone the viewer sees as themselves). A strong hook also uses at least two of: visual interrupt · relevance signal (the viewer's situation, or the audience named) · promised outcome · open loop (always closed later).
**Principles:** sell the outcome, not the feature; identity and future-state lines ("What if you woke up actually rested?") usually beat feature lines ("Track your sleep with AI") · clear beats clever · if you talk about it, show it · specific beats vague (a real number, a named audience, an exact moment) · negative and contrarian framings often stop more people, but never shame the viewer · the ad must not look like an ad (native, phone-real) · humour and edge when the brand allows · don't open on the logo or the app name · no price in the hook for cold traffic (a free trial can open the ad when it's the real offer).
---
## Step 1 additions: Brand Kit and the audience's pains first
Hooks are built on the **Brand Kit** and on the **real pains of the audience**. Before any idea:
1. **Find the Brand Kit:** the one in the chat, the one assigned to the workflow, or `list_brand_kits` (one kit → use it and say so; several → ask which). No kit → ask the user to send it or connect one (base Reference I).
2. **Read it fully** and pull out a short **pain map**:
- **Audience:** who, which segments, their situation and daily moments where the problem shows up.
- **Pains:** what hurts, in their words if the kit has them; what they already tried and why it failed.
- **Desires:** the outcome they want, the identity they want ("someone who sleeps", "someone who has money left").
- **Objections:** why they hesitate.
- **Product truth:** real features, claims, offer, proof, tone of voice, must include / must exclude, forbidden claims.
3. **If the pains are missing, vague or too generic**, don't block: write 3 to 5 **pain hypotheses** from the app card (each one line, in the audience's words) and ask the user to confirm, pick or correct them. Still propose hook ideas in the same message so work moves.
4. **Intake quiz** (base Step 1: one message, multiple choice, options from the Brand Kit, the recommended option first, 4–8 questions; skip what the task or the kit already answers), with these questions plus the base quiz questions that apply:
- Body already (mode A, hook multiplier) or not (mode B)? Where does the old hook end? Is it a validated winner? Its hook rate, hold rate, CTR if known.
- Which pain or segment to lead with, if the kit has several (offer your recommendation).
- Hook preference: visual, verbal, combined, or "you decide" (default: you decide and explain).
- Cold or warm traffic; the store link for research; reviews, past winning hooks, viral videos the audience loves.
- How many hooks (default 4)? Tone, types or claims to avoid?
5. **Propose ideas straight away.** Don't wait for perfect input: the first reply already carries the pain map (or hypotheses) and the first hook ideas.
**Defaults (state, don't ask):** cold traffic · bank of 12 to 15 · N = 4 · 9:16 · Reels / TikTok · English · final 10 to 15 s in mode B, body length + hook in mode A · Seedance 2.5 for people, 2.0 for stylized or UI · 720p (1080p on the user's choice) · sound on · voiceover on in mode B.
**Debug path from the numbers:**
| Signal | Diagnosis | What to do |
|---|---|---|
| Low hook rate | The hook doesn't stop people | Stronger visual beat in frame 1, or a sharper pain; if the angle isn't validated, the angle may be the problem (tell the user) |
| High hook rate, low hold rate or CTR, high CPM | Stops the wrong people, or the body doesn't keep the hook's promise | Name the audience in the line, show what they recognise, align the hook with what the body delivers |
| Good hook rate, low hold rate | The body is weak | Not a hook problem: Better (double hook, social proof after the hook, reorder blocks) |
| Good CTR, weak conversion | Offer, store page or expectations | Not a hook problem; check the hook doesn't promise more than the app gives |
## Step 1a: hook research (voice of customer)
When there is a store link, website or reviews; it takes minutes and makes every hook more specific.
1. **Store page / website:** title, subtitle, description, screenshot captions, ratings. Note the brand voice and the real features and claims.
2. **Reviews and comments:** sort into four kinds of language. **Pain** (the frustration before the app) · **Outcome** (what they wanted, the relief) · **Objection** (why they hesitated) · **Discovery** (what surprised them). Keep repeating patterns, drop one-offs.
3. **Alternatives** (when useful): what the audience uses now and what annoys them about it; claims every app in the category repeats (avoid them); what this app does differently that matters.
4. **Add to the pain map** in the app card: main pain · desired outcome · strongest real benefit · differentiator · objections · customer words worth quoting.
Couldn't browse or found nothing → say so and work from the Brand Kit. Never invent reviews, ratings, user numbers, press or awards.
## Step 1b: Lyra Hook templates
1. `list_templates` with tags ["Hook"] (add "UGC" or "Talking Head" for a person to camera).
2. Offer up to 3 that fit the audience, tone and the hook ideas: title + one line why + preview link. The user may pick one, several or none.
3. Picked → `get_template`, `use_template`, then adapt: rewrite the Video Script for the app card and the chosen pain with `update_node`, replace every placeholder ("[App Name]", "[main benefit]"), upload the logo, packshot or screenshots it needs.
4. Templates are fast demos: some use Seedance 2.0 Fast at 720p, some draw UI or a "DOWNLOAD" button. Say once: Seedance 2.5 (people) or 2.0, 720p by default, real screenshots (base Reference D). Follow the user's choice.
Hook templates in Lyra (Oct 2026); always re-check `list_templates`:
**Visual stop, object POV:** Knock, Blinds, Hook door, Camera is in a bag, Fridge Camera, Trunk POV, Empty Cup Hook, Library Shelf Hook, Morning Girl, Pogo Stick Fall.
**Fourth wall / surreal reveal:** Screen Pull, Balcony, Billboard App Reveal, Las Vegas Sphere, Office-core girl.
**Visual metaphor of the pain:** Clear Your Head, Swipe Away the Chaos, Sofa.
**Format hijack:** Breaking news, Interview POV, Stand-Up Comedy, Angry Boss, Hidden Cam, Subway Surfers Switch.
**Product reveal:** Phone Screen Reveal.
---
## Hook base: what you can draw from
A reference, not a menu to tick off. Combine, adapt and invent; always start from the Brand Kit's pain. The ad concept is in brackets where it fits.
### Visual hooks (the picture does the work)
| Type | What it looks like | Watch out |
|---|---|---|
| Physical interrupt | a clap in front of the lens, a knock on the lens from inside, a hand covering then uncovering the lens, an object tossed at the camera, blinds or a door snapping open | must lead into the pain within 3 s; one beat, not a show |
| Mid-action open | start at the peak moment: the phone already flying onto the bed, the mess already everywhere, the reaction already happening | no setup before it |
| Before state | the problem on screen: 47 unread notifications, a chaotic calendar, an empty fridge at 11 pm, the tired face in phone light (Problem) | show it on a person, not only an object |
| Incomplete visual | a strange situation without explanation that the next seconds answer | answer it by 3 to 5 s |
| Transformation cut | hard cut before → after on a beat, same framing and light (Transformation) | specific, believable; no body before/after for health apps |
| Demo first | a thumb already using the core feature on a real screen (Demonstration) | real screenshots only; keep it short |
| Unusual POV | camera inside a bag, fridge, trunk, bookshelf; the person opens it and looks in | the reveal leads to a person who talks or shows the pain |
| Fourth wall | the character looks into, reaches out of or pulls the viewer into the screen | one clear gesture |
| Visual metaphor / hyperbole | the pain made physical: a huge heavy head, notifications flooding the room, a to-do list unrolling to the floor | exact cause and effect order in the prompt |
| Reaction / micro-expression | a genuine face reacting: the pause, the eyebrow, the laugh | not a forced "wow" |
| Sensory / ASMR close-up | tactile macro detail, satisfying motion, 1 to 2 s with no voice | needs a link to the app (a satisfying "done" tick, an inbox going to zero) |
| Format hijack visual | a news studio, a street interview mic, a stand-up stage, an office meeting (Platform Trends) | only formats this audience follows; no real channels or brands |
| Text-first frame | a bold claim or question as the caption on frame 1, over a moving shot | full text at once, no letter-by-letter fades |
### Verbal hooks (a person says it)
| Type | Example line | Watch out |
|---|---|---|
| Pain callout | "Still scrolling at 2 am? This one's for you." | specific pain from the pain map, not generic |
| Audience callout | "Night owls who hate mornings, listen." | the fix when the hook stops the wrong people |
| Diagnosis | "Here's why your to-do list never gets shorter." | the body must give the reason |
| Mistake / contrarian / negative | "Stop setting ten alarms. It's making mornings worse." | challenge the habit, never insult or scare |
| Question with a stake | "Why is your budget gone by the 15th?" | no yes/no questions |
| Confession / low expectation | "I didn't expect a sleep app to actually work." | a creative scene, not a fake review |
| First person | "I used to lose two hours every night scrolling." | never presented as a verified real user |
| Story cold open | "Lying in bed at 3 am. Again." | close the loop in the body |
| POV | "POV: you finally fell asleep before midnight." | must match the audience's real life |
| Identity / future state | "What if you woke up actually rested?" | tied to what the app really does |
| Specific outcome / direct benefit | "I saved my first 200 euros in a month." | numbers only from the Brand Kit or real reviews |
| Objection first | "I thought budgeting apps were a waste of time." | the body answers the doubt |
| Third-person proof | "My sister hasn't missed a deadline since March." | creative scene; real proof only as proof |
| Dialogue | "Wait, you went to bed before midnight?" "Yeah, since…" | short lines, clear roles |
| People talking about the prospect | "She's been 'going to sleep' for two hours." | recognition, never humiliation |
| Compliment | "How are you always on time now?" | shows a real benefit; usually not about looks |
| List / formula | "Two mistakes everyone makes with their savings." | deliver exactly what was promised |
| Insider / what's new | "Nobody tells you this about morning routines." / "This app just changed one thing." | true and specific |
| Unique feature | "It reads every label, so you shop twice as fast." | feature → benefit → why it matters to you |
| Social proof / authority / statistic | a real rating, a real user count, a real expert, a real number | verified only; none available → demo instead |
| Stakes / FOMO | "Every month you wait costs you another 50 euros." | real stakes only, no fear-mongering |
| Offer first | "Seven days free. Here's why I kept it." | warm traffic or real risk reversal; no price |
### Sound (the fourth layer)
An SFX on frame 1 (click, zip, knock, slurp, notification ping), a music hit on the cut, a sudden silence, or a trending sound the audience knows. Sound-led hooks are weak with sound off, so the picture or caption must still carry the idea.
### Catchy and brainrot hooks (app-native, attention-first)
Feed-native formats that win attention by being weird, chaotic, funny or "not an ad". They borrow the language of the feed (memes, AI characters, chats, split screens) and then turn to the app fast. Strongest with Gen Z and Gen Alpha and for casual, social, entertainment, study, productivity and habit apps. For trust-heavy categories (finance, health, premium) borrow the logic (surprise, speed, humour), not the full chaotic look.
| Format | What it looks like | How it turns to the app |
|---|---|---|
| Brainrot absurd | an original absurd AI character or situation, deliberately lo-fi, a confident dramatic voice saying near-nonsense, bass-heavy sound, fast jump cuts | the absurd thing *is* the pain in disguise (a screaming alarm-clock creature = mornings), then a hard cut to a real person and the app |
| Talking object / pet | the phone, the alarm clock, the to-do list, the brain or a pet talks to camera like a colleague | the object complains about the user's habit (the pain) and "recommends" the app |
| AI micro-drama | an episodic mini-series with original characters (fruit, objects, habits as characters), reality-show tropes, a twist each episode | the app is the plot twist or the solution of the episode; a series gives several ads |
| Split screen | top: a person talking or a story; bottom: a satisfying loop (kinetic sand, slime, marble run, an original game-like run) | the story on top is the pain and the app; the loop only holds the eye |
| Story with TTS | a short first-person story read by a synthetic voice over a satisfying or POV background, captions word by word | the story's turn is how the app helped |
| Chat thread | stylised message bubbles appear one by one: "wait, did you actually try it?" | the reply resolves into the app; based on real customer conversations, lightly fictionalised |
| Comment reply | the video opens on a comment bubble: "does this app actually work?" and the creator answers | the answer is the demo; only real comments or clearly hypothetical ones |
| Trend remix | an AI trend mechanic the audience knows right now (action figure in a box, earth zoom out, bullet time, 80s camcorder diary, a dance), with the user's character | cut to the app within 2 to 3 s; the trend has nothing to sell on its own |
| Absurd scale or physics | something impossibly big, tiny or heavy (a giant notification crushing the room, a tiny person drowning in emails) | the app restores normal scale |
| Calm contrast | a slow, quiet, hand-painted or soft scene with gentle music in a loud feed | stands out by contrast, then the app appears as the calm |
**How to use them well:**
- Entertain first, but the link to the pain or the app must land within about 3 s; a weird opener that never connects brings cheap views and weak users.
- One absurd idea per hook, instantly readable; no inside jokes the audience has to research.
- Invent **original** characters and situations. Never use known meme characters (Skibidi, Italian brainrot creatures and the like), real games (Subway Surfers…), shows or brands unless the user owns the rights; the Lyra "Subway Surfers Switch" template needs an original background.
- Deliberately lo-fi is a style; accidentally uncanny is slop. Faces and hands of real-looking people still follow de-slop; brands that ran sloppy AI ads (Valentino, McDonald's NL) had to pull them.
- Chats, notifications and comments are stylised, not copies of iOS, WhatsApp, TikTok or system UI (platforms restrict ads that imitate organic interface elements); no fake read receipts or fake contact photos; a fictional chat is never presented as a real customer conversation.
- Keep the rhythm: a new stimulus every 2 to 3 s (cut, zoom, sound hit).
- Trends move fast: the brainrot peak was late 2025 to early 2026 and some audiences already call it cringe. Use the mechanic, keep it fresh, check what is trending now (TikTok Creative Center, the user's own feed) before building.
- Sound matters most here: a dramatic narrator, sped-up voice, bass hit, a strange jingle. Music is generated from a description (no artist names, no copied tracks).
### What feels stale in 2026 (avoid unless twisted)
Ring-light testimonial that reads as an ad in half a second · forced enthusiasm ("this changed my life", "obsessed") · opening with a feature list · vague before/after · "Hey guys, today I'm…" · logo or app name first · a slow fade in.
---
## Audience awareness: which hooks for whom
App install ads on cold traffic are mostly levels 1 to 3; retargeting 4 to 5. Unknown → mostly cold plus one or two warm.
| Level | The viewer | What usually works |
|---|---|---|
| 1. Unaware | doesn't see the problem as a problem | a relatable moment, a visual metaphor, humour, mid-action, POV, catchy and brainrot formats (talking object, micro-drama, trend remix, split screen); no hard pitch |
| 2. Problem aware | knows the pain, not the fix | pain callout, diagnosis, mistake, before state, first person, people talking about the prospect |
| 3. Solution aware | knows fixes exist, not which | old way vs new way, question with a stake, list, outcome first, transformation cut |
| 4. Product aware | knows the app, not why it's worth it | demo first, unique feature, objection first, compliment, proof |
| 5. Most aware | close to installing | offer first, real proof, a reason to act now (real urgency only) |
## Where hook ideas come from (in this order)
1. **The Brand Kit's pains and desires** (the pain map). Every hook ties to one of them.
2. **Customer words:** lines from real reviews, comments, support messages (the user, the Brand Kit, store research). Short phrases, never long copied reviews; an AI person saying the line is never presented as the real reviewer.
3. **Past winning hooks** of this app (ask for the hook repository), above all when the current winner has a low hook rate.
4. **Modelled viral TikTok / Reels hooks** the audience loves: copy the mechanism (first frame, twist, line structure), never the video, its people or its sound.
5. **The hook base above**, to widen the set.
## Step 2 addition: the hook bank
Before the plan, write the bank in the chat; it is part of the concept the user approves.
- **12 to 15 ideas** by default (30 on request), each a different idea: a different pain, outcome, situation, perspective or format, not one idea reworded. Mix visual, verbal and combined hooks; mix direct (names the app or feature) and indirect (starts with a situation) openers; cover the audience's awareness levels; a few with humour or edge; when the audience and brand fit, one or two catchy or brainrot ideas.
- One line per idea, with tags:
> H07 · combined · problem aware · Problem · pain: "can't fall asleep" · visual: clap in front of the lens, she's in bed in phone light · line: "If your brain starts talking at 2 am, listen." (9 words) · text: "2 am again?" · hypothesis: night-scrollers stop for a sleep pain said in their words
- **Recommend N** for production (default 4) with one line why. A good set of 4 usually has different kinds (at least one visual-led and one verbal-led or combined), different pains or angles from the pain map, different main characters, and one idea from the user's own sources if they have any. Guidance, not a quota: explain your choice.
- After approval, save the whole bank in a user text node "Hook bank" in the workflow (picked ones marked) for the next MORE round.
## Writing one hook
Write the muted version first: the first frame plus text must work with sound off.
- **First frame:** the hook moment at frame 0, already moving. It is also the thumbnail, so it must read on its own.
- **Spoken line** (verbal and combined hooks): aim for about **6 to 10 words**, said within ~3 s; count the words. Start on the key word; no "So", "Okay", "Hey guys". A longer line is fine only if it still lands by second 3.
- **Text on screen:** 2 to 6 words, echoes the line (doesn't contradict it), on frame 1 in full, marked for post (added in the Video Editor, never in a prompt), inside the safe zone.
- **Sound:** what is heard in the first second. Sound stays on at generation. When someone speaks in the clip: no music under the voice ("no music, no background music, no soundtrack, no score" in that clip's prompt, base Reference C). Clips without speech may keep their music hits.
- **Visual beat** (combined hooks): 0.5 to 1 s, then the line starts on top of it or right after; both tell one idea.
**Checks for every line:** one idea · simple (about a 5th grade reading level, no corporate or "AI" marketing words) · sounds natural said aloud · specific to this app, audience and moment (if it could sell a hundred apps, rewrite) · true (nothing outside the Brand Kit, app card or verified research) · different from the other hooks.
Concept line per picked hook (goes into the plan):
> C1H2 · combined · problem aware · Problem · Visual: a clap in front of the lens, she's sitting in bed in phone light at 2 am. Line: "If your brain starts talking at 2 am, listen." Text (post): "2 am again?" Sound: the clap, then silence. Then: her pain (3 to 6 s), the app's wind-down timer (real screenshot), she falls asleep, CTA.
---
## Deliverable and modes
1. A **hook bank** (12 to 15 ideas) saved in a "Hook bank" text node.
2. N hook clips and **N finished videos**, one per picked hook, each in its own Video Editor. All variants share the same body (Brain), CTA (Pocket), music and end card, so the test isolates the hook.
Name every final with a code the media buyer can paste into Ads Manager: `B{batch}-A:{angle}-F:{formula}-C{concept}H{hook}-Iteration`, e.g. `B3-A:SleepIn5min-F:PAS-C1H2-Iteration`. Node label: "Final: C1H2 · combined clap + pain line".
**When MORE is the right move:** right after an ad is validated · hook rate low while hold rate and CTR are fine · a winner fatiguing after 2 to 6 weeks (keep audience and angle, replace only the hook) · a losing streak (new hooks on a past winner). Not this skill: weak body or high CPC → Better; dead angle → new concept or angle (base skill). Only hook texts wanted → stop after the bank.
| Mode | When | What gets built |
|---|---|---|
| **A. Hook multiplier** (true MORE; default when a body exists) | The user has a body: an existing or winning ad, a Lyra workflow, a video to upload | the original ad as control + N new hooks, each a hypothesis; only the first 2 to 3 s change → N Video Editors (hook N + same body, music, CTA) |
| **B. Hook-led short ads** (default when there is no body) | Nothing exists yet | N ads of 10 to 15 s on the default spine: hook → pain → app solves it → CTA; pain, solution and CTA as identical across variants as the hooks allow |
Mode A body sources: the user's own Lyra workflow (build the hooks inside it, in a new Section) or a finished video (create_upload + attach_upload). Results can't be connected across workflows.
### Hook multiplier: testing hypotheses with the same body
Only the first 2 to 3 s change; everything after the cut point stays exactly as it is. That makes each new hook a clean test of one **hypothesis**, and the cheapest way to learn what stops this audience.
**1. Hypothesis per hook.** Every hook in the bank carries one line: "We think [segment] stops for [pain / angle / hook kind / format]." Decide what the round is testing and vary that, keeping the rest close:
- **Which pain or desire** hits hardest (same kind of hook, different pain from the pain map).
- **Which kind** works: visual vs verbal vs combined (same pain, different kind).
- **Which segment** responds: a callout per segment (students vs parents vs freelancers).
- **Which framing:** negative vs positive, question vs statement, identity vs feature.
- **Which format:** UGC person vs catchy or brainrot vs demo.
- **Finer tests** for a winner: same line with a different first frame, or same first frame with a different line.
A round can mix hypotheses, but say which hook tests what, so the result teaches something.
**2. Control.** Keep the original ad with its own hook in the test as the control (champion). New hooks are challengers; a hook wins only if it beats the control on the user's KPI.
**3. The cut point.** Find where the old hook ends (usually 2 to 3 s; ask the user or read the composition in the Video Editor). Trim the body from that point (`trim.sourceStartMs`). Check that the body still makes sense without the old hook: the voiceover doesn't start mid-sentence, no line refers back to the old opening, the first body frame follows the new hook naturally. If the old hook was spoken over the body, trim the VO too and keep the rest identical. The new hook ends on an end state that cuts cleanly into the body's first frame (cut on action, match cut, or a deliberate hard cut).
**4. Scale.** 4 to 6 new hooks per round is a good default; more (up to 10 to 20) when the budget allows, built in rounds from the bank. Each round's winners and losers go to the hook repository with the hypothesis they tested.
**5. Reading the result.** The winning hypothesis is the learning, not only the winning video: a winning pain or segment feeds the next ads, angles and Brand Kit notes; a winning kind or framing becomes the default for the next round.
**Double hook (optional, mode A):** a second proven hook right after the first (0 to 3 s, then 3 to 6 s). Offer as one extra variant when hold rate is low or CPC is high; it is a Better test.
## Best way to build it
The user's explicit choices override any row. Models and prices: base Reference A.
| If the hook is | Best approach (graph) | Models |
|---|---|---|
| **Combined, UGC person** (common default) | character image → hook keyframe (the visual beat at frame 0) → one clip with the beat, then the spoken line in quotes, then the pain; or the hook as its own 4 to 5 s clip trimmed to 1.5 to 3 s | nano-banana-pro · seedance-2.5 |
| **Verbal, talking head** | character image → clip starting mid-sentence, the line in quotes, natural gestures | nano-banana-pro · seedance-2.5 |
| **Visual, no speech** (object POV, metaphor, transformation, ASMR) | hook keyframe → clip 4 to 5 s with exact action order; music or SFX; caption in post | seedance-2.0 (frame) or seedance-2.5 (refs) |
| Dialogue or "people talking about the prospect" | two character images as references → one clip, who says what by [ImageN] | seedance-2.5 |
| Shows the app (demo, feature) | user screenshots → phone image → short clip or UI insert (base Reference D) | seedance-2.0 (frames) or 2.5 (refs) |
| Mode A, same person as the body | a still of that person from the body as reference; no still → a faceless hook | seedance-2.5 |
| Mode B, full short ad | per hook: character → one multi-shot clip 10 to 15 s with "cut to" between hook, pain and solution, or separate clips joined in the Video Editor; VO + music; logo end card | seedance-2.5 · nano-banana-pro |
| Lyra Hook template picked | use_template → adapt (Step 1b) → one Section per hook | as the template, upgraded |
| Double hook variant | hook clip A + hook clip B + body → one extra Video Editor | as above |
| Only hook texts | stop after the bank | none |
| Catchy: talking object, AI character, micro-drama | original character image (nano-banana-pro, the style chosen: lo-fi, cartoon, 3D) → clip with the line in quotes; one character reference for the whole series | nano-banana-pro · seedance-2.0 (stylized) or 2.5 (realistic) |
| Catchy: split screen | top clip (person or story) + bottom clip (original satisfying loop) → Video Editor with two video layers positioned top and bottom (position x/y/width/height), captions in the editor | seedance-2.5 + seedance-2.0 |
| Catchy: chat thread, comment reply | message or comment images designed with exact text in quotes (stylised, not a copy of a real messenger) → laid over the video in the Video Editor, one by one | nano-banana-pro + video_composer |
| Catchy: trend remix | the trend mechanic as an image or clip with the user's character → hard cut to the app part | per trend: seedance-2.5 or kling (frames) |
| Many hooks, tight budget | hook clips on a draft model, rerun winners on the recommended one | seedance-2.0-fast |
**Hook clip length.** Seedance's minimum is 4 s: generate 4 to 5 s, put the hook beat in the first 1.5 to 3 s, plan a clean cut point (end state) into the next shot, trim in the Video Editor.
**Layout.** Section "Hook bank" (text node), one Section per hook (its nodes + its Video Editor), one Section for the shared body, music and VO. Labels: "C1H1: clap + pain (frame)", "C1H1: clap + pain (clip)", "Final: C1H1 · clap + pain".
## Video Editor per hook
One `video_composer` per hook, in playback order: hook clip → body clip(s) → end card, then VO and music. Everything except the hook is identical across variants: same body trims, same music (starting at 0 so the hit lands on every hook), same body VO and CTA, same end card. Keep the hook's own sound or line; lower the body clip's sound if it clashes. Hook text and captions are added in the editor UI: tell the user what to add and where. Captions, if the user wants them (asked in the approval message), follow the base rule (`lyra-video-editor` → Captions: size 80, at 75% of the height, under the face); the hook text on frame 1 is a headline, placed in the safe zone. If the hook opens a loop or promises a list, check the body delivers it.
## Run options for hooks
**Run order, not a menu** (base Step 6): after the user's yes, run all of it in this order without offering options. Stop between stages (the look first, then the rest) only when the user asked for it, or when the plan is expensive and that was said in the approval message.
As in the base skill, credits read from the nodes and multiplied by N; the hook bank costs nothing. **A. Hook images (recommended):** all N keyframes and characters · **B. Hook clips** for the frames the user picked · **C. Everything** → N Video Editors.
---
## Prompt rules (hooks)
| Node | Write | Avoid |
|---|---|---|
| Hook bank (text node) | each idea with number, kind (visual / verbal / combined), awareness level, main character, pain, visual, line, text, word count; picked ones marked | long explanations |
| Hook keyframe | the hook moment itself at frame 0: the visual beat mid-action or the person mid-sentence, the pain visible, phone-real for UGC, 9:16 | an establishing shot; text; drawn UI or logos |
| Hook clip | action from frame 1; for combined hooks, the exact order ("she claps once in front of the lens, lowers her hands, looks into the camera and says: '…'"); the surprise readable in ≤1.5 s; spoken line in quotes; who says what in dialogue; cause and effect; the end state at the cut point | slow build up; two surprises; the caption text in the prompt; a polished "ad" look |
| Hook VO (if separate) | the exact hook line as its own short VO node; body VO shared | filler openers; price; claims not in the Brand Kit |
No third-party brands, games, channels, landmarks used as brands, or famous people in prompts unless the user owns the rights.
## Truth and brand safety
- **Brand safety** (Lyra's System Preamble, base Reference B): no profanity, no political statements, no unsubstantiated health claims, no competitor disparagement. The Brand Kit's **forbidden claims are enforced absolutely**, in every hook line, caption, first frame and VO; if the user asks for one, say once that it is on the kit's forbidden list and leave it out unless the user confirms the kit is outdated.
- Hooks never carry a claim, number or offer that isn't in the Brand Kit or the user's message; a provocative or negative hook challenges a habit, never the viewer, a group or a competitor.
## Common mistakes (hooks)
| Mistake | Prevention |
|---|---|
| A hook clip where someone speaks comes with music under the voice | No-music sound line in every clip with speech; our music in the Video Editor |
| Hooks written without reading the Brand Kit | Pain map first; every hook tied to a real pain or desire |
| Waiting for perfect input before proposing anything | Pain hypotheses + first ideas in the first reply |
| Visual beat and line say two different things | One idea per hook across all layers |
| A visual trick with no link to the pain | The trick leads into the pain by second 3 |
| Two weak hooks stacked instead of one strong | Stack only when each layer adds something |
| Video credits spent on untested ideas | Hook bank first; the user picks |
| N hooks that are one idea reworded | Different pains, kinds, mechanisms, main characters |
| Generic line that could sell any app | Specific to this app, audience, moment |
| Hook type doesn't match the audience | Awareness table |
| Body, music or CTA differ between variants | Lock the body; only the hook changes |
| Logo intro, fade in, "Hey guys", feature list first | Frame 1 already moving; pain or outcome by second 3 |
| Hook promises what the app or body doesn't deliver | Promise only what the app card supports |
| Invented reviews, ratings, numbers, press, testimonials | Verified sources only; no proof → demo |
| Viral video copied instead of modelled | Mechanism only |
| Hook clip set to 1.5 s (rejected) | Generate 4 to 5 s, trim |
| Different face in hook and body | Body still as reference, or faceless hook |
| Template run as it came | Adapt per Step 1b |
| Hook multiplier without a control or without a stated hypothesis | Original ad as control; one hypothesis line per hook |
| Remnants of the old hook in the body (VO mid-sentence, a line about the old opening) | Cut point checked; body and VO trimmed cleanly |
| Brainrot opener that never connects to the app | Pain or app by about second 3 |
| Known meme characters, real games or a copied trend video | Original characters and backgrounds; the mechanic only |
| Chat or notification that copies iOS / WhatsApp / system UI, or a fake chat sold as real | Stylised bubbles, real or clearly fictional content |
| Chaotic brainrot look on a trust-heavy brand | Borrow the logic, not the look |
## Quality gates (hooks)
- **Stage 0 (bank, Claude checks before sending):** every idea tied to a pain or desire from the pain map? Different ideas, kinds and awareness levels? Layers of each hook tell one idea? Lines simple, specific, true, sayable, counted? No invented proof?
- **Stage 1 (images):** each hook moment reads in one glance, muted, even as a thumbnail? The N hooks clearly different? Same person as the body where needed?
- **Stage 2 (clips):** action from frame 1? Visual beat and line in the planned order? Surprise lands in ≤1.5 s? Line clear? Clean cut point? Native, not an ad?
- **Stage 3 (finals):** every final opens on its hook? Pain recognisable right after it? The app's role clear? Body, music and CTA identical across variants? Loops and lists paid off? Text 2 to 6 words in the safe zone? Each final named with its code? In hook multiplier: control included, old hook fully removed, hypothesis written for each variant?
## After the test
Hooks are hypotheses. Tell the user how to read the test in one short block:
- Launch all variants the same day, one ad set per concept in an ABO campaign.
- First signals at 2,000 to 4,000 impressions; judge each ad at 5,000+ impressions, never on day one.
- **Hook rate** (3 s views ÷ impressions): target above 40%; 2026 medians are about 28% on Meta and 33% on TikTok, top 10% about 45% and 55%; below 20% is weak. **Hold rate** (ThruPlays ÷ 3 s views): target above 30%. Compare with the account's own averages.
- Sales and profit → winner · no sales → not a winner, but an outstanding hook rate earns one more test · sales without profit → worth another test. No winner → next ideas from the bank, or a different pain or angle.
- Judge winners by CPA / ROAS (cost per install, trials, payers), not hook rate alone.
Then offer: save winning and losing hooks (hypothesis, kind, pain, line, visual, hook rate) to a **hook repository** doc in the project; the next round from the unused bank; the winning hook on other ads of the same angle; Better on the winner; other sizes or languages (matching skills). A winner lives about 2 to 6 weeks: start the next round before it fatigues.
lyra-workflow-layout17.1 KB
View saved version →
---
name: lyra-workflow-layout
description: "Canvas layout for every Lyra workflow Claude builds or changes, in the house style of Lyra's templates - nodes grouped into sections in run order (a Section is a frame node), a small STEP sticky note above every section that says what happens there and what the user can change, the creative team's color code (lime the idea and script, pink the user's own app assets, violet generation, rose the result), a clear reading path (the idea on the left, the steps stacked in columns, the Video Editor on the right), clear node labels, no stray or empty nodes, and a final check. Use whenever a Lyra skill creates or edits a workflow (video, UGC, hooks, short drama, UI motion, statics, carousels, competitor copies, variations, concept multiplier, resize, translation, brand kit starter), and for \"make the workflow clear\", \"tidy up the canvas\", \"sign the sections\", \"add notes for the user\", \"the canvas is confusing\", \"lay it out like the templates\"."
---
# lyra-workflow-layout
Helper skill for every Lyra skill. The other skills decide **what** to build; this one decides **how it reads on the canvas**. Every workflow Claude builds or changes is laid out by this file.
**The goal.** Anyone who opens the workflow (the user tomorrow, a teammate, a client) understands in ten seconds what it makes, in which order it runs, and where to change something by hand. A canvas of unlabelled nodes in one row is a black box. A canvas split into colored sections, each with its own small STEP note, reads like a recipe, the way Lyra's own templates do: first the idea, then what the user brought, then the heroes, the scenes, the clips, and the final video.
**Who decides what.** The creative skill decides which sections its creative needs (its "Layout" lines). This file decides how they are placed, numbered, explained, colored, labelled and checked. The user's explicit wishes win over both.
**This is a way of thinking, not a script.** Use judgment when a canvas needs something different, and say why in one line. Fixed: every node in a section, one STEP note per section, steps in run order, the color code, labels a person understands, no empty or stray nodes, and Lyra's technical limits below.
---
## The house style: how Lyra's templates are laid out
Lyra's templates (Creators workspace, Templates) are made by the creative producers, and they all follow one pattern:
- **A reading path.** The script on the left, the work sections in the middle stacked top to bottom, the Video Editor on the right. The eye goes left to right, and top to bottom inside a column.
- **A small STEP sticky note above every section**, in the section's color, numbered in the order the user goes through it:
- "STEP 1 · Check the script"
- "STEP 2 · Insert a screenshot/video of your app."
- "STEP 3 · Generate Image & Video"
- "STEP 4 · Generate Music · You can create your own music and combine it with the video in the Video Editor"
- "STEP 5 · Combine scenes"
- **Each note is short:** the step number, a 2 to 5 word action, at most one helper sentence. Plain instructions, no explanations of the tech. One note per section, never one big note with all the steps.
- **Color by kind of step:** lime for the script, pink for the user's own app assets, violet for every generation, rose for the final assembly.
- **One section per kind of work, with its nodes side by side**, flowing left to right inside it.
The templates also have slips that Claude's canvases never repeat: "Gerate", duplicate or missing step numbers, a STEP 0, "STEP 3&4", notes in the wrong color, "(copy)" and "Note (" labels, the editor called Composer in one note and Video Editor in the next, a "Generate Music" note in a workflow with no music node, empty leftover notes and empty upload nodes.
---
## What the tools can do (Lyra, Oct 2026)
Re-check at the start of a build: tools change.
| Need | How | Notes |
|---|---|---|
| A section | `create_frame_node` (workflow_uuid, node_uuids, label) | The label is the section's title, shown in one line above it. **The size is fixed at creation** from where its nodes are at that moment, plus padding; it never shrinks later. So place the nodes first, create the frame second. |
| Section color | `update_node` on the frame: `{"note_style": {"background_color": "#c4b5fd80"}}` | Width and height can't be set. |
| Add nodes to a section later | `update_node` on the frame: `{"node_uuids": [the full list]}` | The whole list. If the section must change size, delete the frame (its nodes stay) and create it again. |
| A STEP sticky note | **Not in the MCP tools.** In a browser signed in to Lyra: the **+** button in the bottom toolbar → Tools → **Note** adds one. Then `update_node` on the note: `{"content": "…", "note_style": {"background_color": "…"}}` | The note's size stays 240×200, enough for a STEP note. Existing notes (in a workflow from a template) are edited the same way. |
| Positions | **Not in the MCP tools.** In a browser signed in to Lyra, a short script on the workflow page can move nodes through the canvas's own change handlers (`onNodesChange` with position changes, then `onNodeDragStop` with the moved nodes); Lyra saves it like a drag. Read the nodes' sizes from the page first | New nodes otherwise land in one row in creation order. Keep the user's tab off the workflow while the MCP tools edit it, and close the page before MCP edits, or the page can save an older canvas over them. |
| Tidy automatically | The **Organize nodes** button (bottom toolbar, four squares) | Lays the graph out by its connections. Unconnected nodes (the script, notes) go to the end, so the script lands far from the start and **notes are thrown to the edges**. Use it only on a canvas without notes and only when hand placement isn't possible. |
| A text card | `create_user_text_node` | A real text node: never connect it to anything, or its text feeds the next node. Only the fallback for a STEP note when no browser is available. |
| Run one step | The **Run** button on a section's top right corner | Runs every node of that section. |
| Remove an empty or stray node | `delete_node` | Only nodes that hold nothing and feed nothing (an empty upload), or Claude's own leftovers; say which in the report. Anything with content: ask first. |
---
## Layout: the reading path
Place the sections on a grid, like the templates:
```
column L column M1 column M2 column R
┌───────────┐ ┌─────────────────────┐ ┌─────────────────────┐ ┌──────────────┐
│ note ST1 │ │ note ST2 │ │ note ST6 │ │ note last │
│ SCRIPT │ │ YOUR APP (pink) │ │ KEYFRAMES │ │ VIDEO EDITOR │
│ (lime) │ ├─────────────────────┤ ├─────────────────────┤ │ (rose) │
└───────────┘ │ note ST3 │ │ note ST7 │ └──────────────┘
│ CAST │ │ CLIPS │
├─────────────────────┤ ├─────────────────────┤
│ note ST4 PLACES │ │ END CARD · MUSIC │
└─────────────────────┘ └─────────────────────┘
```
- **Column L:** the idea: script, brief, concept card (lime), at the top.
- **Middle columns:** the steps in order, top to bottom, then the next column: the user's own materials first (pink), then the heroes, the places, keyframes, clips, end card, voiceover, music.
- **Column R:** the Video Editor or the final outputs (rose), at the height of the clips.
- **Each section:** its STEP note on top (left-aligned with the section, ~40 px gap), then the section with its nodes in one row, left to right in their own order (keyframe → clip, clip 1 → clip 4). More than 5–6 nodes → two sections ("Clips 1–3", "Clips 4–6").
- **Spacing:** 40 px between nodes, ~140 px between a section and the next note below it, columns wide enough that nothing overlaps (a row of 4 image nodes is ~1600 px).
---
## Sections
1. **One section per step of work, in run order.** Every node sits in exactly one section. Nothing floats outside, nothing is kept "just in case".
2. **One STEP note per section**, above it, in the section's color. Numbering STEP 1, 2, 3… with no gaps, no repeats, no STEP 0, no "3&4", no "2.1".
3. **The section title is short**, because the note carries the step: "Story script", "Your app & style", "Cast", "Keyframes", "Video clips 1–3", "Music", "Video Editor".
4. **Size:** 1 to 6 nodes per section. A section with one node only for the script, the Video Editor, the music or a single upload.
5. **Never** the whole graph in one section, never a section per node, never an "unused" section: empty nodes are removed (see the tools table), real content gets a real step.
### Color code
Always the 50% transparent hex (ending in `80`). The note and its section have the same color; the same kind of step has the same color across the canvas.
| Color | Hex | Kind of section | What goes in |
|---|---|---|---|
| Lime | `#bef26480` | The idea, text to read and check | Script, brief, concept card, story, hook bank, carousel script, Text Split |
| Pink | `#f9a8d480` | The user's own materials | Screenshots, logo, app icon, packshot, end card or app video, product photo, style reference, brand assets |
| Violet | `#c4b5fd80` | Generation | Characters, places, keyframes, phone shots, clips, voiceover, music, Image Resize, Image Translation |
| Rose | `#fda4af80` | The result | The Video Editor; the final ads or sizes the user downloads |
| Slate | `#cbd5e180` | Reference kept for analysis (nothing runs) | A competitor's ad, a teardown, prompt tips, when the creative needs them |
### STEP notes
The pattern, the same as the templates:
```
STEP 2
Your app & style
Added: Lull Home screen, Lull logo and the art style reference. Swap them to change the app.
```
- Line 1: `STEP N`. Line 3: the action in 2 to 5 words ("Check the script", "Our heroes", "Generate keyframes", "Generate video", "Generate music", "Combine scenes"). Line 5: one sentence: what's in the section or what the user can do ("You can…", "Edit a prompt and press Run.", "Added: …").
- For the user's materials, the note lists what was added ("Added: logo, 3 screenshots").
- In the user's language (English when the canvas and the audience are English); the words the user sees in Lyra: section, node, prompt, Run, Video Editor, Edit Video, Render. Never tool names, uuids or connection roles.
- Short: it must fit 240×200 without scrolling.
**Examples** (video): "STEP 1 · Check the story script · The idea, every line of dialogue and the timing of all clips." · "STEP 3 · Our heroes · Emma and Dan. Every scene uses them as references." · "STEP 5 · Generate keyframes · One image per clip. Edit a prompt and press Run." · "STEP 7 · Generate music · You can create your own music and combine it with the video in the Video Editor." · "STEP 9 · Combine scenes · Open Edit Video to trim and add captions, then Render."
### Standard sections by creative
The creative skill's own Layout lines say which sections it needs; these are the defaults.
| Creative | Sections in reading order (color) |
|---|---|
| Video ad (base, UGC, short drama, UI motion) | Script (lime) → Your app (pink, when there are uploads) → Cast (violet, when there is a person) → Places / Keyframes → Clips → Voiceover → Music (violet) → Video Editor (rose) |
| Hooks | Hook bank and script (lime) → Your app (pink) → one section per hook with its keyframe and clip (violet) → shared body, voiceover, music → the Video Editors (rose) |
| Short drama | Story (lime) → Your app & style (pink) → Cast → Places → Phone shots → Clips per act → End card → Music (violet) → Video Editor (rose) |
| Static ads | Concept (lime) → Your app (pink) → Persona / product (violet) → Ads (violet, or rose when last) → Sizes and languages (rose) |
| Carousel | Story and Text Split (lime) → Your app and persona → Cards in one row in card order (rose when last) |
| Competitor copy | Competitor reference, analysis only (slate, first, its own note "Reference · not connected") → the normal set |
| Variations, multiplier, audience variations | The original layout kept in each variation; notes and labels updated where the person, setting or angle changed |
| Resize, translation added later | A new section with the next STEP number, placed after the last step |
| Brand Kit starter | Brand assets (pink) · Brand Kit notes: app card, pain map, open questions (slate) |
---
## Node labels
- **Say what it is and where it belongs:** "Scene 2 · app demo · keyframe", "Scene 2 · app demo · clip", "Character · Mia", "Screenshot · timer screen", "Logo", "VO · full script", "Music · lo-fi", "Hook A · clap + pain · clip", "Ad C1 · 2 am POV · 4:5", "Card 3 · fix · 4:5".
- **Default labels only for the single node of its kind:** "Video Script", "Music Brief", "Voiceover Script", "Video Editor". The final assembly node is always called **Video Editor**.
- **No step numbers in node labels** (the note carries the step), no "(copy)", no "Image 1", no "Upload Image", no empty label.
- **One pattern per kind of node**; the same scene, card or hook number in its keyframe, clip and caption.
---
## Build order
1. **Plan.** The plan table (the base skill's Step 2) gets a Section column; the approval message lists the steps in one line ("STEP 1 Script → STEP 2 Your app → STEP 3 Cast → … → Video Editor").
2. **Nodes and connections** as the creative skill says. Remove Claude's leftovers and empty nodes.
3. **Notes:** one per section. In the browser: **+** → Note, once per section; then close the workflow page and set each note's text and color with `update_node`.
4. **Positions:** open the workflow, place every note and node on the grid (Layout above) with the page script, check that it saved (reload), close the page.
5. **Sections:** `create_frame_node` for each section **after** its nodes are in place, then `update_node` for its color. Notes stay outside the frames, above them.
6. **Look:** open the workflow, Fit view, screenshot, check the reading path and that nothing overlaps.
7. **Check** (below), fix, check again.
8. **Report** the steps in the chat with the same words as the notes, plus what the user does next.
**No browser available** (only the MCP tools): put a text card with the STEP text as the first node of each section (label "STEP N"), create the frames, and tell the user once: "Press Organize nodes in the bottom toolbar, then drag the Script section to the left." Offer to finish the layout when a browser is available.
---
## Templates, variations and the user's own workflows
**A workflow made from a template (`use_template`).** Keep the template's own layout: its notes and sections were placed by the producers. Fix the notes with `update_node` (typos, continuous numbers, colors from the code, "Video Editor", notes that no longer match their nodes). Never press Organize nodes there. Nodes Claude adds get their own note and section, placed at the right step with the page script.
**Variations** (`create_variation`) copy the whole canvas with its layout. Keep it; update the notes and labels that name what changed. Each variation has its own nodes: lay out each one.
**The user's own workflow.** Don't rearrange or delete without asking; add Claude's nodes in new noted sections and offer the tidy-up in one line.
**Follow-ups on a workflow Claude built** (a new hook, a size, a language): a new note and section with the next STEP number, placed after the last step.
---
## Check before handing over
`get_workflow` and a screenshot:
- [ ] Every node that isn't a frame or a note appears in exactly one frame's `node_uuids`.
- [ ] One note per section, above it, same color; STEP 1 to N continuous, in reading order.
- [ ] The script section is first (left, top); the Video Editor last (right).
- [ ] No empty nodes, no "unused" section, no one big note with all the steps.
- [ ] No "(copy)", "Image 1", "Upload Image" or empty labels; the editor is "Video Editor".
- [ ] Text cards (if any) are connected to nothing.
- [ ] Nothing overlaps; every section hugs its nodes (no big empty frames).
- [ ] All connections, prompts and results the same as before the layout.
## Common mistakes
- One big note with every step instead of a note per section.
- Organize nodes on a canvas with notes, or the script left wherever Organize put it.
- Frames created before the nodes are placed (they keep the old, huge size).
- An "unused" section full of empty uploads.
- Editing through MCP while the workflow page is open (the page saves an older canvas).
- STEP 0, gaps, repeats, "3&4"; a note that says one thing while the nodes do another.
- Step numbers in node labels; titles in a language the user doesn't use.
lyra-workflow-review28.4 KB
View saved version →
---
name: lyra-workflow-review
description: "Review any Lyra workflow and explain it in plain words - what it makes and in which order it runs, section by section - then find what is wrong (broken connections, invalid nodes, empty nodes, nodes with no result, dead ends, settings that don't match), price a full rerun and each part of it, and, if the user wants, fix the problems and tidy the canvas by lyra-workflow-layout. Read-only by default - in a workflow Claude did not build in this chat, nothing is deleted, moved or changed without the user's yes. Use for \"review my workflow\", \"explain this workflow\", \"what does this workflow do\", \"why doesn't it run\", \"check my canvas\", \"is anything broken here\", \"how much to rerun it\", \"how much does this template cost\", \"audit this workflow\", or a Lyra workflow link with a question about it."
---
# lyra-workflow-review
Core skill for reading a Lyra workflow the way a creative producer would. The creative skills build workflows; `lyra-fix` repairs one part of a finished ad; `lyra-workflow-layout` decides how a canvas reads. This one opens any workflow (the user's own, a teammate's, a template copy, one Claude built last week), says what it does, what is wrong with it and what a run costs, and only then offers to change anything.
**The goal.** The user sends a link and gets back, in one message: what this workflow makes, its steps in order, a short list of problems with how to fix each one, and the price of running it all again or only a part. Nothing on their canvas has moved.
**Core rules come from the base skills.** Credits, pre-run check, picking a result, links and the open canvas rule live in Part 1 of `lyra-video-ad-generation` (video) and `lyra-static-image-generation` (images). Canvas rules (sections, STEP notes, colors, labels) live in `lyra-workflow-layout`. Fixing a scene or an image goes to `lyra-fix`. This file only adds what is specific to a review.
**This is a way of thinking, not a script.** Fixed: read before saying anything, plain words, every problem with its fix, prices from the nodes, never guess a result you haven't seen, and the hands-off rule below.
---
## The hands-off rule
A review **reads**. It does not change the workflow.
- **A workflow Claude did not build in this chat** (the user's own, a teammate's, a template copy, an older one): nothing is deleted, moved, renamed, reconnected, rerun or tidied without the user's yes to that exact change. Not even an empty upload node, not even a typo in a note.
- **A workflow Claude built in this chat:** Claude may fix its own leftovers (an empty node, a lost connection) and say so in one line; anything the user touched stays as they left it.
- **A yes covers what was listed,** nothing more. "Fix the connections" is not a yes to tidy the layout.
- **Big changes go into a variation** (`create_variation` "{name} · review fixes", `switch_variation`) so the original stays as it was: a tidy-up of the whole canvas, deleting nodes, changing many prompts. Offer it in the same message; small fixes (one setting, one connection) can go in place.
- **What the tools do behind the scenes** (say it before the yes, not after):
- `switch_variation` makes that variation the one Lyra shows and runs **and renames the whole workflow after it**. After the work, say which variation is now main and offer to switch back.
- `delete_node` **cannot be undone** and also clears every frame or reference setting that used the node. Content is never deleted without a yes naming the node; when in doubt, disconnect instead of deleting.
- `disconnect_nodes` clears the target's frame or reference settings that used the source: name them in the plan.
- `update_node` keeps old results; nothing is lost by changing a setting, but the old prompt is overwritten: quote old → new in the report.
- **Never run nodes to check them.** A run costs credits; a review costs nothing.
---
## Step 1. Find and read the workflow
1. **Which workflow.** A link `lyra.splitmetrics.com/workflows/{uuid}` → the uuid. A name → `list_workflows` with `search`; several matches → list them (title, last updated) and ask which. Nothing given → the most recently updated one, named in the first line so the user can correct it.
2. **Which variation.** `get_workflow` reads the main variation. If the user is asking about another one (`list_variations`), `switch_variation` only with their yes, because it changes which version Lyra shows and runs and renames the workflow after it; otherwise review the main one and name it.
3. **Read it now, not from memory:** `get_workflow` (nodes, `data`, `is_valid`, `validation_error`, `credits`, `estimated_generation_time`, edges, the Video Editor's `video_rendering_composition`), `list_workspaces` (credits), `list_node_configs` (models and allowed settings), and the Brand Kit if one is assigned (`brand_kit_uuid`; `null` = no kit, say so). There is no tool to read one kit by its uuid: find it in `list_brand_kits` (page through) by `uuid`.
- **Which balance.** Lyra works in the workspace the user last selected, and `list_workspaces` doesn't mark which one that is (and can fail: "Could not load workspaces"). With a browser, read it off the Lyra sidebar: the workspace name at the top, **Credits** at the bottom. Otherwise: one workspace → its credits; several → name the one you assume ("balance in {workspace}") or ask once; never show a number from another workspace as "your balance".
- **The Video Editor** is the node with `action: video_composer`, whatever its label ("Video Composer", "Video Editor", or a custom name).
4. **A big canvas.** A library canvas with many creatives can return 60 000+ characters and come back as a saved file. Read all of it (jq or a short script), never review from the part that fit. Count nodes by type first to see what you're dealing with.
5. **Several creatives on one canvas.** Split the graph into groups that are connected to each other (each usually ends in its own Video Editor or final images). Name each group from its section title or STEP notes. First send a short list: each creative in one line (what it makes, its node count, the number of problems found, its full rerun price), plus the nodes connected to nothing. Then ask which ones to review in full, and review each picked group as its own creative (Steps 2–5).
6. **Results and pictures.** `get_workflow` does not list each node's results, and no tool lists them without a run uuid. What `get_workflow` does show:
- the Video Editor's composition: every clip on a track has `sourceNodeId` and `sourceResultUuid`; **no `video_rendering_composition` at all = the Video Editor was never opened or assembled**. Read the clips' ids only: a track has its own `sourceNodeId` too, which doesn't point to a node. **A copied edit:** a workflow made from a template (or copied) can carry the template's whole edit, with clip `sourceNodeId`s that are not nodes on this canvas and asset urls from the template's runs. None (or almost none) of the clip ids on the canvas → one finding, not one per clip: "the edit was copied from the template and shows the template's video; it needs re-assembling after this workflow's own runs". A clip id that is on the canvas means the edit used that node's result at some point, not that the node has a result now;
- frames in `image_inputs_usage`: `image_result_uuid` (a pinned result) or `null` (Lyra's selected one);
- uploads: `files` with the file's url and name; **no `files` = an empty upload**;
- nothing else.
For generated nodes, open the workflow in a browser signed in to Lyra (read only, nothing clicked): a screenshot after Fit view shows which nodes have an image, video or audio result; `get_page_text` returns the text results (the script a Video Script node wrote, with its scenes, timing and lines), every prompt, the count on each node ("x1") and the run history ("3 runs"). Read the text result before explaining what a script node makes. No browser → ask the user. Never write "no result" for a node you couldn't see: write "not checked".
7. **Open canvas.** Reading is safe with the workflow open. Before any edit later (Step 6), the workflow page must be closed: with a browser under Claude's control, move the tab off the workflow while editing and open it again at the end to show the result; otherwise ask the user to switch their tab away.
---
## Step 2. Explain it in plain words
Build the picture from the edges, not from the node list order (that is creation order, not run order).
1. **What it makes.** The last node(s): a Video Editor → one video ad of {length} s in {ratio}; image nodes with nothing after them → {N} images; several Video Editors → {N} videos (hooks, versions). One line.
2. **The run order.** Sort the nodes by their edges: sources first (uploads, scripts, text), then what takes from them, the Video Editor last. Group by section when there are sections (a frame's `node_uuids`), in the order of the STEP notes when they exist.
3. **Each step in one line,** in the user's words, not the tech:
- what goes in and what comes out ("a photo of the heroine on the sofa → it becomes the first and last frame of the video");
- the model in plain words, by its name in `list_node_configs` ("Nano Banana Pro, the most realistic image model", "Kling 3.0 Pro, 10 s with its own sound");
- what the user can change there ("her outfit is in this prompt").
4. **The user's own materials:** uploads, screenshots, logo, the Brand Kit, and what each one feeds.
5. **Text on the canvas.** Three kinds, say which:
- **Note** (`action: note`, the sticky note with "Write a note..."): can't be connected to anything and never changes a generation. STEP notes and tips live here.
- **User Text** (`user_text`, free): text written by a person. Connected to a generation node (image, video, audio, another text node), it goes into that node's generation as it is: say "this text feeds {node}". It still doesn't keep a character consistent by itself; that comes from the character image connected as a reference.
- **Text generation nodes** (Video Script, Voiceover Script, Music Brief, Creative Analysis, Character Prompt, Text Split…: they have a `model_name` and `credits`): a language model writes a new text from the node's prompt and its inputs, and that text goes to the next node. The prompt on the canvas is the instruction, not the final words; the real text is the node's result. Rerunning it writes a new text.
A User Text or text generation node connected to nothing is only for reading, like a Note.
6. **Short.** 5 to 10 lines for a normal workflow. Long prompts are summed up in a few words, never pasted. Text only, no diagram: the canvas already shows the connections.
> **Microphone UGC** makes one 10 s vertical UGC video with music.
> 1. **Script** (Video Script, GPT): from the brief (she taps her microphone once and says a 3-line testimonial) it writes the video's prompt.
> 2. **The heroine** (Image G/ STEP 1, Nano Banana Pro): her on a beige sofa in a sunny living room, holding a clip-on mic.
> 3. **Second frame** (Image G/ STEP 2): the same shot, her finger on the mic; made from image 1.
> 4. **The video** (Video G/ STEP 3, Kling 3.0 Pro, 10 s with sound): starts on image 2, ends on image 1, speaks the script.
> 5. **Music** (lo-fi, 10 s) and **Video Composer** (the Video Editor): the clip with the music under it at 26%.
> (The edit was most likely copied with the template: the workflow was never updated after it was created. And the labels say STEP 3 for the video while the notes put image and video together in STEP 2: both go to Problems.)
---
## Step 3. Find the problems
Go through every check. Each problem gets: **where** (the node label, in quotes), **what** in plain words, **why it matters**, **the fix**, and its weight:
- **Blocks** — the node won't run, or runs with something missing.
- **Wastes credits** — it runs, but spends on nothing or makes the wrong thing.
- **Confusing** — it works, but a person reading the canvas gets lost.
### Connections
| Check | How to see it | Weight |
|---|---|---|
| An edge to or from a node that no longer exists | edge uuid not in `nodes` | Blocks |
| A frame or reference set but not connected | `image_inputs_usage.first_frame / last_frame.node_uuid` with no edge from that node | Blocks |
| A pinned result that's gone | `image_result_uuid` set, the source node rerun or cleared (check in the browser) | Blocks |
| A video node that needs images but gets none | `use: frames / references`, no image edge in | Blocks |
| Frames chosen, but no frame set | `use: frames`, `first_frame` and `last_frame` both `null` (Lyra still says valid) | Blocks |
| An image connected to a video with no role | an image edge in, no `image_inputs_usage` on the video node: the model decides (most start from the image) | Confusing (say what will likely happen; offer to set frame or reference) |
| The Video Editor uses a clip from a node that is gone or disconnected | a clip's `sourceNodeId` not in `nodes`, or in `nodes` but not connected (all of them gone → the copied edit, Step 1.6: one line) | Blocks (that clip is a dead copy) |
| A node is connected to the Video Editor but not in the edit | edge in, no clip with that `sourceNodeId` | a paid node: Wastes credits (paid, not used) · an upload: Confusing (often an optional logo or screenshot slot) |
| A text node connected by accident | a script, brief or note-like text feeding a generation node it shouldn't (its text becomes the prompt) | Wastes credits |
| Two prompts fight | the node has its own prompt and a text node feeds it too, with different content | Wastes credits |
| A dead end | a paid node that feeds nothing and isn't a final output. Final outputs: every Video Editor; in a creative with no Video Editor, the last image or video nodes. In a creative that has a Video Editor, a clip, voiceover or music with nothing after it is a dead end | Wastes credits (ask: an alternative take kept on purpose?) |
| An island | a group of nodes connected to nothing else on the canvas | Confusing (ask: kept on purpose?) |
| Wrong order | scene, card or hook numbers in the labels out of order along the edges ("Scene 3" feeds "Scene 1 · clip"), or clips in the edit not in the order of their numbers | Confusing or Wastes credits |
### Invalid nodes
**`is_valid: true` is not enough.** Lyra's check misses a lot: an upload with no file, a node with no prompt, and a setting value the model doesn't list (e.g. `duration: -1` on Seedance 2.5, which takes `"adaptive"`) all come back valid. Check every node against `list_node_configs` yourself.
| Check | How to see it | Weight |
|---|---|---|
| `is_valid: false` | read `validation_error` and translate it ("no resolution set", "this model doesn't take a last frame") | Blocks |
| A model Lyra no longer offers, or a setting not in `list_node_configs` | compare `model_name` and every value with the model's allowed ones. When `list_node_configs` contradicts itself (Seedance 2.0: the description allows `-1`, the minimum says 4), mark it "unverified", not Blocks | Blocks |
| `credits: null` on a paid node | a setting is missing (e.g. no resolution) | Blocks |
| The model can't use what it's given | read the model's parameters in `list_node_configs`: references on a model with no `reference_images` (Kling 3 Pro, Veo 3.1 Fast, Sora 2) · frames and references together (Seedance: one or the other) · a last frame without a first frame · Veo 3.1 references with a ratio other than 16:9 or a length other than 8 s · a motion-control model without its reference video · a Sora first frame in another ratio than the video · a ratio set on a model that ignores it when a first frame is given (Kling) | Wastes credits (the input is ignored) or Blocks |
| Settings don't fit together | a 16:9 clip from a 9:16 frame · a clip shorter than its voiceover · music shorter than the video · the Video Editor canvas a different ratio or length than its clips | Wastes credits |
| A voiceover with no voice or language chosen | no `voice` / `language_code` in `data` (Lyra's default voice will be used) | Confusing (ask if that's on purpose) |
| The prompt says one thing, the settings another | "10-second" in the prompt, `duration: 5`; "vertical" with 16:9; "no music" with music connected | Wastes credits |
| A clip where someone speaks has no music ban | speech in the clip (a spoken line in the script or prompt, `generate_audio: true`) and no "no music, no background music" sound line: the model may lay its own music under the voice, which can't be removed (`lyra-video-ad-generation` → Reference C) | Wastes credits |
| Speech that doesn't fit the clip | the lines in the script (its text result) need more time than the clip's `duration` at a calm pace (~2.5 words/s) | Wastes credits |
| A prompt or script asks for something that isn't there | "use the provided voiceover script" with no voiceover node; "the logo from [Image2]" with one image connected | Wastes credits |
### Empty nodes
| Check | How to see it | Weight |
|---|---|---|
| An upload with no file, connected to something | no `files` in `data` | Blocks (or a blank layer in the edit) |
| An upload with no file, connected to nothing | no `files`, no edges | Confusing |
| A generation node with no prompt and no text fed in | no `prompt` in `data`, no text node edge in | Blocks |
| A text generation node with no prompt | it writes from its inputs only; say what it will write from | Confusing |
| An empty note, an empty section (a frame with no `node_uuids`), a User Text with no text | | Confusing |
| An ad with no app | no Brand Kit, no app name in any prompt, and the script talks about "the app" | Wastes credits (the ad sells nothing) |
| A placeholder left in a prompt: "[App Name]", "(app name)", "{product}", "<app>", "TBD", "XXX", "Lorem" | search every `prompt` and note, case-insensitive, even when a Brand Kit is assigned (the kit doesn't fill a placeholder in a prompt) | Wastes credits (the model draws or says the placeholder) |
| Markdown left in a prompt (`**`, `*`, `#`) | search every `prompt` | Confusing (the model may read the stars literally) |
### Nodes without a result
| Check | How to see it | Weight |
|---|---|---|
| A node never run | the browser shows no result; no clip in the composition | — (say it; it's the cost in Step 4) |
| A node waits for an input that has no result | its source has no result | Blocks (run the source first) |
| The Video Editor was never assembled | no `video_rendering_composition` in `data` | — (say it: the video isn't made yet) |
| The Video Editor's edit is empty, or holds old clips | no clips on the tracks; or a clip's `sourceResultUuid` is an older take than the one picked on the node (browser) | Blocks / Confusing |
| A failed run | the browser shows an error on the node | Blocks (the fix by base Runtime failures) |
### Inside the edit (when there is a composition)
| Check | How to see it | Weight |
|---|---|---|
| A placeholder clip left in the edit | a "Text" or empty clip with no content | Confusing |
| Clips overlap on one track, or gaps between them | `startMs` + `durationMs` of neighbouring clips | Confusing |
| The edit is shorter than its clips, or music shorter than the edit | `canvas.durationMs` vs the clips; the music clip's `durationMs` | Wastes credits (cut off) |
| Music too quiet or too loud | the music track's `volume` against `lyra-video-editor` → Audio | Confusing (ask) |
| An older take in the edit | the clip's length doesn't match the node's `duration` now | Confusing |
| Old asset links | asset urls on another domain (e.g. `muse.splitmetrics.com`) | Confusing (check they still play) |
### Canvas (by `lyra-workflow-layout`)
Only the points that make the canvas hard to read; full layout checks belong to the tidy-up (Step 7). Typos in notes ("Gerate"), leftovers in note text (` `, `**`, a STEP pasted twice: "Combine scenesSTEP 5"), steps missing, repeated or out of order, a note that names a node that isn't there (a "Generate Music" note with no music node), the editor called Composer in one place and Video Editor in another, step numbers in labels ("Image G/ STEP 2"), default labels ("Upload Image", "Image 1", "(copy)"), nodes outside any section, overlaps. All **Confusing**.
### What a review does not judge
Whether the idea is good, the script is strong or a picture looks right is a creative opinion: give it only when the user asks, in a separate short block, or hand over (`lyra-result-check` to look at a finished video or image for defects, `lyra-fix` to repair one, the creative skill for a new angle). The Brand Kit: point out only a clear mismatch (another app's name in a prompt, a claim the kit forbids). **No Brand Kit** (`brand_kit_uuid: null`): say it in one line and offer in Step 5 to assign one (`list_brand_kits` → `assign_brand_kit`) or build it with `lyra-brand-kit`; assigning changes the workflow, so it waits for a yes like any fix.
---
## Step 4. What a rerun costs
Prices come from `credits` on the nodes (one run of the node; an Image Resize with two ratios already counts both). Never guess; a paid node with `credits: null` is priced "unknown until {setting} is set". A video on adaptive or auto length (`adaptive`, `-1`) is priced at the model's longest length (Seedance 2.5: 30 s, 855 credits at 720p): say "up to".
**Text nodes in a rerun.** Rerunning a text generation node (Video Script, Voiceover Script, Music Brief…) writes a **new** text, so everything after it can change, not only the picture. Price "everything" both ways when the workflow has text generation nodes: with the texts rewritten, and keeping the texts (only the media nodes). Keeping them is the default for "rerun the same ad".
1. **Everything.** The sum of `credits` of every node that generates (images, video, audio, resize, translation), without the text generation nodes by default (above), plus a second line with them. Skip: frames (a Section's `credits` is already the sum of its nodes; counting both doubles it), notes, uploads, user text, the Video Editor (free).
2. **By section.** The Section's `credits`, or the sum of its nodes when there are no sections, per step.
3. **From a node on.** For the parts the user is likely to redo (each clip, the character, the music): that node plus every node downstream of it along the edges, the Video Editor last. This is the price `lyra-fix` will quote, so the user sees it before they ask.
4. **Only what has no result yet** — when some nodes were never run: the price to finish the workflow.
5. **Time:** add up `estimated_generation_time` along the longest chain of nodes (nodes of the same stage run side by side), min to max. A Section's time is its slowest node, not the time of the whole section.
6. **Balance** of the right workspace (Step 1.3), and whether the full rerun fits.
> | Rerun | Nodes | Credits |
> |---|---|---|
> | Everything, same script | Heroine 23 · Frame 2 23 · Video 504 · Music 13 | **563** |
> | Everything, new script | + Video Script 1 | 564 |
> | From the heroine on | Heroine → Frame 2 → Video → Video Editor | 550 |
> | Only the video | Video → Video Editor | 504 |
> | Only the music | Music → Video Editor | 13 |
> Balance {X} in {workspace} · the full run takes about 3.5–6 min (heroine → frame 2 → video).
---
## Step 5. The review message
One message, in the user's language, in this order:
1. **The workflow:** name, link `https://lyra.splitmetrics.com/workflows/{uuid}`, the variation, the Brand Kit (or "none").
2. **What it does** (Step 2).
3. **Problems** (Step 3), heaviest first: Blocks → Wastes credits → Confusing. One line each with its fix. Nothing found → say so in one line ("No broken connections, no invalid or empty nodes"), and what wasn't checked ("results not checked: no browser").
4. **Costs** (Step 4).
5. **One question** with the offers, each with its cost and where it goes (in place or a variation):
> Want me to fix it? I can: (1) put your logo into the empty "Upload Image" (it's the template's logo slot) or leave it as it is, (2) replace "[App Name]" in the script with Lull, (3) tidy the canvas by the Lyra template style in a variation, so your version stays as it is. The fixes are free; after (2) the script and the video need a rerun, 505 credits. Which ones?
No changes in this message. Several problems of the same kind → one line ("4 upload nodes with no file: …").
---
## Step 6. Fix what the user picked
Only what the yes covered, by the hands-off rule.
1. **Open canvas** (Step 1.7): tab off the workflow before editing.
2. **Variation first** if the fix is big or the user chose it.
3. **Make each change:** `connect_nodes` / `disconnect_nodes`, `update_node` with values from `list_node_configs`, `delete_node` only for nodes the user named. For a video node change the whole `image_inputs_usage` from `get_workflow` with one field changed (`lyra-video-ad-generation` → Step 7, Picking a result).
4. **A fix in a result** (six fingers, a warped logo, a wrong ending) → `lyra-fix`; a new person, angle or size → its variation skill. Say it in one line and hand over.
5. **Check:** `get_workflow` again; every fixed node `is_valid`, every planned edge there, nothing else changed (other prompts, settings, connections, picked results). Lost something by accident → put it back and say so.
6. **Runs** only on a separate yes with the price (Step 4), by the base pre-run check and run order.
7. **Report:** what changed, node by node, old → new in a few words; what's left; the link. Then open the workflow again for the user to see.
---
## Step 7. Tidy the canvas (on request)
Offered in Step 5, done only on a yes, by `lyra-workflow-layout`:
- **A template copy:** keep the producers' layout; fix the notes (typos, continuous numbers, colors, "Video Editor") and the labels; never Organize nodes.
- **The user's own canvas:** a full tidy-up moves every node, so do it in a variation by default ("{name} · tidy"), unless the user says "in place". Notes, sections, colors, labels and positions by the layout skill; connections, prompts, settings and results untouched.
- **Labels the user wrote** are renamed only when they break the pattern badly or the user agrees; list the renames before doing them.
- Finish with the layout skill's check list and a screenshot.
---
## Common mistakes (review)
| Mistake | Prevention |
|---|---|
| Deletes an "empty" node in someone's workflow without asking | Hands-off rule: list it, fix only on a yes |
| Tidies the canvas because it looked messy | The tidy-up is an offer; in a variation by default |
| Explains in node order | Run order from the edges |
| Reports every clip of a copied edit as a broken link | One line: the edit came with the template |
| Offers to delete an empty upload that is an optional slot | Offer to fill it or leave it |
| Trusts `is_valid: true` | Check uploads (`files`), prompts and every setting against `list_node_configs` |
| Reviews ten creatives in one wall of text | A short list first, then full reviews of the picked ones |
| Reviews half of a big canvas | Read the whole saved output |
| "Rerun everything" rewrites the scripts unasked | Price it with the texts kept and with new texts |
| Switches a variation without saying it renames the workflow | Say it first; offer to switch back |
| Pastes long prompts into the explanation | A few words per step |
| "No result" on a node Claude never saw | "Not checked"; look in the browser or ask |
| Runs a node to see if it works | Never run during a review |
| Counts a Section and its nodes, doubling the total | Skip frames in the sum |
| Prices a rerun from memory or an old table | `credits` on the nodes now |
| A problem without a fix | Every problem: where, what, why, fix |
| A list of 20 small things | Group the same kind into one line; heaviest first |
| Judges the idea or the pictures unasked | Only on request, separately |
| Changes more than the yes covered | Each change named before it's made; check with `get_workflow` after |
| Edits while the workflow page is open | Tab off the workflow first |
---
## Quality gates (review)
- **Before sending the review:** read with `get_workflow` now? The final output named? Steps in run order, in plain words? Every check in Step 3 done, "not checked" where Claude couldn't see? Each problem has where, what, why, fix and weight? The costs from `credits`, sections not double counted, the balance next to them? One question, no change made? A canvas with several creatives: the short list first?
- **After fixes:** only the agreed changes made · everything else the same (prompts, settings, connections, picked results, positions unless a tidy-up was agreed) · every fixed node valid · the old version kept where it was a variation · the workflow opened again for the user.