@officexapp/vidfarm-devcli 0.21.43 → 0.21.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/.agents/skills/editor-capabilities/SKILL.md +4 -0
  2. package/.agents/skills/vidfarm/SKILL.md +95 -17
  3. package/.agents/skills/vidfarm/harnesses/explainer.HARNESS.md +1 -1
  4. package/.agents/skills/vidfarm/harnesses/product-demo.HARNESS.md +2 -0
  5. package/.agents/skills/vidfarm/harnesses/short-form.HARNESS.md +1 -0
  6. package/.agents/skills/vidfarm/recipes/local-edit-render-approve.md +1 -1
  7. package/.agents/skills/vidfarm/recipes/onboard-a-new-director.md +1 -1
  8. package/.agents/skills/vidfarm/references/agent-included-imagegen.md +75 -0
  9. package/.agents/skills/vidfarm/references/assets-and-sourcing.md +152 -2
  10. package/.agents/skills/vidfarm/references/automation-and-local-dev.md +22 -9
  11. package/.agents/skills/vidfarm/references/browser-harness.md +93 -0
  12. package/.agents/skills/vidfarm/references/content-ideas.md +232 -10
  13. package/.agents/skills/vidfarm/references/core-workflows.md +11 -1
  14. package/.agents/skills/vidfarm/references/editor-workflows.md +39 -0
  15. package/.agents/skills/vidfarm/references/onboarding.md +1 -1
  16. package/.agents/skills/vidfarm/references/primitives.md +51 -0
  17. package/.agents/skills/vidfarm-media/SKILL.md +2 -0
  18. package/SKILL.director.md +775 -42
  19. package/SKILL.md +157 -115
  20. package/crowdsourcing.md +417 -3
  21. package/dist/src/cli.js +750 -34
  22. package/dist/src/devcli/agent-imagegen.js +181 -0
  23. package/dist/src/devcli/browser-harness.js +384 -0
  24. package/dist/src/devcli/clip-store.js +41 -3
  25. package/dist/src/devcli/consult.js +14 -0
  26. package/dist/src/devcli/cost-mode.js +23 -3
  27. package/dist/src/devcli/doctor.js +52 -3
  28. package/dist/src/devcli/hyperframes-cli.js +11 -1
  29. package/dist/src/devcli/local-render.js +4 -7
  30. package/dist/src/devcli/marketplace-gigs.js +623 -0
  31. package/dist/src/devcli/qa-check.js +89 -1
  32. package/dist/src/devcli/shared-folder.js +387 -0
  33. package/dist/src/devcli/skill-docs.js +61 -7
  34. package/dist/src/devcli/stills.js +4 -8
  35. package/dist/src/lib/ffprobe-path.js +64 -0
  36. package/dist/src/lib/render-media-prep.js +2 -11
  37. package/dist/src/services/clip-curation/ffmpeg.js +4 -15
  38. package/dist/src/services/clip-curation/index.js +1 -1
  39. package/dist/src/services/clip-curation/local-agent.js +6 -2
  40. package/dist/src/services/clip-curation/media-select.js +146 -3
  41. package/experimental/google-news-to-video.md +235 -0
  42. package/package.json +8 -150
  43. package/public/assets/file-directory-app.js +35 -35
  44. package/public/assets/homepage-client-app.js +15 -15
  45. package/public/serve-shells/library-files.html +5 -1
  46. package/public/serve-shells/library-raws.html +10 -1
  47. package/public/serve-shells/tools-clipper.html +5 -1
  48. package/public/serve-shells/tools-image.html +5 -1
  49. package/public/serve-shells/tools-video.html +5 -1
@@ -1,20 +1,69 @@
1
- ## Content ideas — the angle bank
1
+ ## Content ideas — frames, awareness stages, and problem angles
2
2
 
3
3
  Read this when a director says **"give me content ideas"**, "what should I post", "I need 30 videos for the month", "I'm out of ideas", or when a batch run needs N *different* videos instead of N variants of one video.
4
4
 
5
5
  **This also runs FIRST for a brand-new director, before the cold-start interview.** It needs one line of offer, not an interview; it is offline, free, and keyless; and it hands the director 20+ titled videos in about a minute. That is the easiest win available on turn one, and their reactions to the list ("this one, not that one") are better raw material than anything an interview gets cold. Run it, save `content-ideas.md`, then offer the interview as the way to turn ideas into a strategy — `references/onboarding.md` → *Start with content ideas*.
6
6
 
7
- **What this is.** A fixed bank of **50 content frames**. A frame is a reusable shape for a video's subject not a hook line, not a script. You take the director's topic (their offer, their niche, their product, their audience's world) and pour it into a frame: `the rise of` + `dropshipping supplements` → *"The rise of the supplement dropship store"*. One topic against 50 frames is 50 distinct videos, and they do not read as repeats, because each frame changes what the video is *about*, not just how it opens.
7
+ **What this is — three banks, not one.** An idea is a point in a small grid, and this reference holds all three axes:
8
+
9
+ | Axis | Bank | Question it answers |
10
+ |---|---|---|
11
+ | **Subject** | the director's own pool of adjacent topics | *What is this one about, in the niche?* (settling the dinner argument · eating what you actually craved · reading a menu before you commit) |
12
+ | **Frame** | 50 content frames | *What is the video the story of?* (`the rise of`, `then vs now`, `one decision that changed everything`) |
13
+ | **Awareness** | 5 stages | *What does the viewer already know?* (unaware → problem-aware → solution-aware → product-aware → most-aware) |
14
+ | **Angle** | 44 problem angles | *From which side do we talk about the problem?* (the hidden cost, the myth, the confession, the honest downside) |
15
+
16
+ A **frame** is a reusable shape for a video's subject — not a hook line, not a script. You pour the director's topic into it: `the rise of` + `dropshipping supplements` → *"The rise of the supplement dropship store"*. An **angle** decides which face of the problem that video shows; the same frame at two angles is two genuinely different videos. An **awareness stage** decides who it is allowed to be for — the same idea aimed at a stranger and at a buyer needs different first ten seconds and a different ask.
17
+
18
+ **The grid is where the volume comes from.** 50 frames × 44 angles × 5 stages, over a pool of adjacent subjects, is not a number to take literally, but it is why "I need 30 videos this month" is an easy ask, not a hard one. Vary **two** axes across a set and it never reads as repeats. Vary only one and it does — and the axis most often left frozen is the subject, because the offer line is right there and it is easy to paste.
8
19
 
9
20
  **How to use it (the loop).**
10
21
 
11
22
  1. **Get the topic.** In priority order: read the director's **`OFFER.md`** if one exists (see `onboarding.md`); **if they named a URL** — "content ideas for my offer example.com" — **fetch the site and read it** (home page, plus the pricing and about pages when they exist) and pull the offer, the audience, the promise, the objections, and the product vocabulary straight off the page; otherwise ask for the offer, the niche, and the audience in one question. Never generate ideas against a topic you guessed. When you work from a URL, **state the offer you read back in one line before the list** ("Reading example.com: a $49/mo bookkeeping tool for solo trades") so the director can correct it before you produce 20 ideas off a wrong premise — and offer to save that line plus the ideas as `OFFER.md` + `content-ideas.md` in their folder.
12
- 2. **Pick frames, don't dump the list.** Choose 1020 frames that actually fit the topic and the audience's awareness stage a solution-unaware audience wants `what everyone gets wrong` and `how it works`; a product-aware audience wants `then vs now`, `cheap vs expensive`, `one decision that changed everything`. Say the frame name next to each idea so the director can ask for more of that shape.
13
- 3. **Write each idea as a title, not a frame.** Output `"The one pricing mistake that killed our first 400 orders"`, not `"one mistake that changed everything about pricing"`. A frame that stays abstract is not an idea yet.
14
- 4. **Then run it through the hook harness.** A content idea is the *subject*; it is not the four charges. Every idea a director picks still needs hook / loop / payoff / bait written before the timeline — `references/hooks-and-virality.md`. The frames on this list are deliberately curiosity-shaped, which makes the loop easy to name, but never skip that pass.
15
- 5. **Batch it properly.** If the director wants the whole set produced, that is scripting mode with a `HARNESS.md``recipes/bulk-scripting-with-a-harness.md`. One frame per video, one line in the plan file.
23
+ 2. **Name the problem in the director's words, once — then write 48 adjacent ways to say it.** Every angle is a lens on *a problem*; if you have not written the problem down in one sentence, the angles all collapse into the same vague video. Take it from `OFFER.md`, from the site's own copy, or ask: *"What is the thing that is going wrong for them right now, in their words?"* That sentence is the *first* entry in a **subject pool**, never the only one see *The subject pool* below. One frozen phrase is what turns 50 frames into 50 versions of one video.
24
+ 3. **Spread across awareness stages, not just frames.** Most directors post everything at one stage usually product-aware, because that is the stage they live in and then wonder why the account does not grow. Cover the ladder deliberately; the default monthly mix is in *Spreading a month across the ladder* below. Say the stage next to each idea.
25
+ 4. **Pick frames and angles, don't dump the lists.** Choose 10–20 combinations that actually fit the topic. Label each idea `frame · angle · stage` so the director can say "more like that one" and you know exactly which axis they mean.
26
+ 5. **Write each idea as a title, not a frame.** Output `"The one pricing mistake that killed our first 400 orders"`, not `"one mistake that changed everything about pricing"`. A frame that stays abstract is not an idea yet.
27
+ 6. **Then run it through the hook harness.** A content idea is the *subject*; it is not the four charges. Every idea a director picks still needs hook / loop / payoff / bait written before the timeline — `references/hooks-and-virality.md`. The frames on this list are deliberately curiosity-shaped, which makes the loop easy to name, but never skip that pass.
28
+ 7. **Batch it properly.** If the director wants the whole set produced, that is scripting mode with a `HARNESS.md` — `recipes/bulk-scripting-with-a-harness.md`. One idea per video, one line in the plan file, with its stage and angle recorded so the set stays balanced.
29
+
30
+ **Give lots when asked.** "Give me content ideas" means volume. Return **20+ titled ideas** by default, grouped by frame family or by awareness stage, not three polite suggestions. The director prunes; you supply.
31
+
32
+ ### The subject pool — adjacent, not literal
33
+
34
+ **The most common defect in a generated list is not a bad frame. It is one frozen phrase.** The offer line goes in verbatim, and every title carries it:
35
+
36
+ > The history of deciding where to eat tonight
37
+ > The rise of deciding where to eat tonight
38
+ > The future of deciding where to eat tonight
39
+ > The science of deciding where to eat tonight
40
+
41
+ The frame moved four times. The video did not move once. A director reads that list and correctly says it is one idea with four openings.
42
+
43
+ **The fix is a pool, not a sentence.** Before you write a single title, write **4–8 adjacent subjects** inside the same niche — different ways the same audience says the same life, from different sides of it:
44
+
45
+ | Frozen | Adjacent pool for the same offer |
46
+ |---|---|
47
+ | deciding where to eat tonight | settling the food argument · picking a restaurant before you read a single review · the craving you cannot place · eating what you actually wanted · the group chat that never picks · reading a menu before you commit |
48
+
49
+ Now the same four frames are four videos:
50
+
51
+ - *The history of settling the food argument*
52
+ - *The rise of picking dinner by review score*
53
+ - *The future of eating what you actually craved*
54
+ - *The science of the craving you cannot place*
55
+
56
+ **Adjacent means inside the niche, and true.**
57
+
58
+ - ✅ **Adjacent:** the same audience, the same day, the same pain seen from another side — the group chat, the diet rule, the menu, the argument, the craving, the five open tabs, the walk to a place that turned out wrong.
59
+ - ❌ **Off topic:** a different business. "The rise of the restaurant industry" is not this offer's video; "the psychology of ordering the same thing every time" is.
60
+ - ❌ **A rebrand of the product line.** Swapping adjectives on the offer sentence — *finding where to eat tonight*, *choosing where to eat tonight* — is the frozen phrase wearing a hat. If the subject has not changed, the video has not changed.
61
+
62
+ **Where the pool comes from.** The audience's own vocabulary: the objection, the workaround they already tried, the moment before the search, the moment after the wrong choice, the person who is not the buyer but is in the room. `OFFER.md`, the site copy, and real comments are all pools you can read out rather than invent.
63
+
64
+ **Do it for each lens.** The subject can sit on the *problem*, on the *category*, or on the *product* — and the pool is per lens, because a frame that claims a past cannot take a new product as its subject. Rotate the pool as you go down the list: no two ideas in a row should repeat the same phrase.
16
65
 
17
- **Give lots when asked.** "Give me content ideas" means volume. Return **20+ titled ideas** by default, grouped by frame family, not three polite suggestions. The director prunes; you supply.
66
+ **One rule to check the finished list.** Read the titles with the frames covered up. If what is left is the same sentence 20 times, you produced one idea, not 20.
18
67
 
19
68
  ### The 50 frames
20
69
 
@@ -92,6 +141,175 @@ Read this when a director says **"give me content ideas"**, "what should I post"
92
141
  - the complete breakdown
93
142
  - the rabbit hole
94
143
 
144
+ ### The awareness ladder — 5 stages
145
+
146
+ Eugene Schwartz's ladder, as a production instrument. The stage decides **what the first ten seconds are allowed to assume** and **what the video is allowed to ask for**. An idea is not finished until it has a stage, because the same subject at the wrong stage is a video that talks past the viewer.
147
+
148
+ `vidfarm ideas --stages` prints this ladder; `--stage <name|n>` prints one stage.
149
+
150
+ **Stage 1 · unaware** — they do not have a name for the problem yet, and they are not looking for one.
151
+
152
+ - **Believes:** nothing is wrong; this is just how it is. They are on the app to be entertained.
153
+ - **Video must:** be interesting on its own merits, then leave one splinter — a situation they recognise from their own week.
154
+ - **Frames that fit:** the rise of · the psychology of · what nobody noticed · the untold story · one event that changed everything · the rabbit hole
155
+ - **Angles that fit:** the daily friction · the two kinds of people · the confession · the screen recording · the industry does this on purpose
156
+ - **Ask:** none. A follow at most. Naming a price here burns the video.
157
+ - **Never:** open with the problem stated as a problem — they do not agree it is one yet.
158
+
159
+ **Stage 2 · problem-aware** — they feel the pain and can describe it, but they think it is unavoidable or their own fault.
160
+
161
+ - **Believes:** "this part of my job is just miserable." They blame themselves, their discipline, or bad luck.
162
+ - **Video must:** articulate the pain better than they can, then move the blame off them and onto a cause.
163
+ - **Frames that fit:** why it failed · what everyone gets wrong · the biggest mistakes · expectation vs reality · problem vs solution · the chain reaction
164
+ - **Angles that fit:** the hidden cost · the slow leak · the advice that broke it · the wrong metric · the expensive lesson · the day it broke
165
+ - **Ask:** a comment or a save. "Which one is you?" works; a link does not.
166
+ - **Never:** name the product in the first half. They have not accepted that a solution category exists.
167
+
168
+ **Stage 3 · solution-aware** — they accept a fix exists somewhere, but not that this *kind* of fix is the one.
169
+
170
+ - **Believes:** "someone has solved this, but the options I have seen are junk / too expensive / not for me."
171
+ - **Video must:** make the category legible and prove the mechanism. This is the explainer stage.
172
+ - **Frames that fit:** how it works · why it works · myth vs reality · simple vs complicated · cause vs effect · the complete guide
173
+ - **Angles that fit:** the mechanism · the false solution · the myth · the experiment · what pros do differently · the receipts
174
+ - **Ask:** "Want the breakdown?" — a comment keyword, a saved post, a free resource.
175
+ - **Never:** compare to named competitors yet; that is a stage-4 conversation and it reads as defensive here.
176
+
177
+ **Stage 4 · product-aware** — they know your product exists, and they are weighing it against alternatives and against doing nothing.
178
+
179
+ - **Believes:** "it might work, but not for my situation / not at that price / not worth the switch."
180
+ - **Video must:** face one specific objection and answer it with evidence, not adjectives.
181
+ - **Frames that fit:** then vs now · cheap vs expensive · beginner vs expert · best vs worst · one decision that changed everything · theory vs evidence
182
+ - **Angles that fit:** the price objection · the "it won't work for me" objection · the honest downside · the before/after · the client story · the risk reversal
183
+ - **Ask:** the direct one. Link, demo, trial, DM keyword.
184
+ - **Never:** re-explain the problem from scratch. They have heard it; repeating it wastes the hook.
185
+
186
+ **Stage 5 · most-aware** — buyers, users, and the people who already like the director.
187
+
188
+ - **Believes:** "I'm in. What is new, and what am I missing?"
189
+ - **Video must:** give a reason to act now, or a use they had not thought of.
190
+ - **Frames that fit:** what happened next · the complete breakdown · how it changed · the future of · after it disappeared
191
+ - **Angles that fit:** the window closing · what just changed · the file itself · the process, unedited · the number nobody posts
192
+ - **Ask:** the offer, plainly, with the deadline or the limit that makes now different from next month.
193
+ - **Never:** pad it. This audience wants the update, not the setup.
194
+
195
+ **Mapping to the `brainstorm/awareness_stages` primitive.** The cloud primitive takes a 2×2 — `problem_awareness` × `solution_awareness` — which collapses this ladder: `problem_unaware + solution_unaware` = stage 1; `problem_aware + solution_unaware` = stage 2; `problem_aware + solution_aware` = stages 3–4; and stage 5 is the customer list, which the primitive does not model. Use the ladder to plan the mix, and the primitive when the director wants generated angles for one specific state (`references/onboarding.md`).
196
+
197
+ ### Spreading a month across the ladder
198
+
199
+ A month of posts at one stage is the most common failure in a director's calendar, and it looks like "good videos, no growth" (all stage 4) or "big views, no sales" (all stage 1). Default mix for 30 posts, adjusted afterwards for the account's size:
200
+
201
+ | Stage | Share of a 30-post month | Why |
202
+ |---|---|---|
203
+ | 1 · unaware | 9 (30%) | Reach. This is what brings new people in; it is the only stage that grows the audience. |
204
+ | 2 · problem-aware | 9 (30%) | The conversion engine of organic. Cheap to make, and it recruits from stage 1. |
205
+ | 3 · solution-aware | 6 (20%) | The explainer library. Long-lived; these keep working for months. |
206
+ | 4 · product-aware | 3 (10%) | Objection handling. Also the best paid-ad candidates. |
207
+ | 5 · most-aware | 3 (10%) | Launches, updates, deadlines. More than this reads as constant selling. |
208
+
209
+ `vidfarm ideas --grid --topic "<offer>" --count 30` lays a month out in exactly this mix, and draws each row's angle and frame from the stage's own lists above.
210
+
211
+ **Skew it deliberately.** A brand-new account with no audience runs 1 and 2 heavier and can skip 5 entirely. An account with traffic but no sales inverts the top: more 3 and 4. A launch week is allowed to be mostly 4 and 5 for that week only — then go back to the mix.
212
+
213
+ ### The problem angles — 44 lenses
214
+
215
+ An angle is **which side of the problem the video approaches from**. It is not a hook, not a frame, and not a format. Two videos on the same subject at two angles do not feel like repeats, which is why the angle bank — not the frame bank — is what you reach for when the director says *"I already covered that topic."*
216
+
217
+ `vidfarm ideas --angles` prints the bank, `--angle <family or name>` filters it, `--grid --topic "<offer>"` pairs angles with frames.
218
+
219
+ **Pain & consequence — what it is costing them**
220
+
221
+ - the daily friction — the small annoyance they have stopped noticing, shown in full
222
+ - the hidden cost — what it silently costs per month, counted in their units, not dollars
223
+ - the slow leak — nothing breaks; it just bleeds, and the video shows the bleed rate
224
+ - the worst case — where this ends if nothing changes, played out on one real example
225
+ - the thing they already tried — name their failed workaround before they can bring it up
226
+
227
+ **Enemy & blame — moving the fault off the viewer**
228
+
229
+ - the industry does this on purpose — the incentive that keeps the problem alive
230
+ - the advice that broke it — a popular tip, followed correctly, producing the damage
231
+ - the middleman — who takes a cut for work the viewer could do or skip
232
+ - the tool everyone recommends — why the default choice is the wrong one here
233
+ - the rule nobody questions — an unwritten norm that has no reason behind it
234
+
235
+ **Belief & myth — what they are sure of that is not true**
236
+
237
+ - the myth — the sentence the niche repeats, taken apart
238
+ - the false solution — the fix that treats the symptom and hides the cause
239
+ - the wrong metric — they are optimising the number that does not pay them
240
+ - the survivor's tale — the success story that is unrepeatable, and why
241
+ - the advice that expired — true five years ago, wrong now, still repeated
242
+
243
+ **Mechanism & proof — why this actually works**
244
+
245
+ - the mechanism — the how, drawn out in steps a stranger can follow
246
+ - the receipts — the numbers on screen, unretouched, with the ugly ones left in
247
+ - the experiment — a real A/B, including the version that lost
248
+ - the before/after — same input, two treatments, one frame each
249
+ - third-party proof — someone with no stake saying it
250
+
251
+ **Identity & status — who they become**
252
+
253
+ - the two kinds of people — a sorting line the viewer places themselves on
254
+ - the tell — the small signal that gives an amateur away
255
+ - the room you get into — what changes socially, not functionally
256
+ - what pros do differently — the boring habit behind the impressive result
257
+ - the permission slip — telling them the thing they wanted to stop doing is fine to stop
258
+
259
+ **Confession & story — I lived this**
260
+
261
+ - the confession — the mistake the director made, named with the number attached
262
+ - the expensive lesson — what it cost to learn, stated first, before the lesson
263
+ - the day it broke — one dated incident, told in order
264
+ - the client story — someone else's arc, with their permission and their words
265
+ - the comment that started it — a real DM or reply as the cold open
266
+
267
+ **Insider & access — you were not supposed to see this**
268
+
269
+ - the screen recording — the actual doing, unedited, no narration for the first beat
270
+ - the number nobody posts — the metric the niche hides
271
+ - what gets said off-camera — the version without the marketing voice
272
+ - the file itself — hand over the template, the sheet, the prompt, on screen
273
+ - the process, unedited — full length, real time, mess included
274
+
275
+ **Objection & risk — why they do not buy**
276
+
277
+ - the price objection — say the price out loud and defend it with arithmetic
278
+ - the "it won't work for me" objection — the edge case they think they are
279
+ - the "I don't have time" objection — the real time cost, measured
280
+ - the risk reversal — what happens if it fails, and who carries that
281
+ - the honest downside — who this is genuinely wrong for, named plainly
282
+
283
+ **Urgency & change — why now and not later**
284
+
285
+ - the window closing — a real deadline, limit, or seasonal edge
286
+ - what just changed — a new rule, price, platform change, or release
287
+ - the cost of waiting — the same decision made now vs in six months, priced
288
+ - the first-mover gap — what the early ones get that the late ones cannot
289
+
290
+ ### Frame × angle × stage — the grid
291
+
292
+ The grid is the answer to "give me 30 different videos" and to "I already made a video about that."
293
+
294
+ 1. Write the problem in one sentence.
295
+ 2. Pick the **stage** first — it constrains the other two, and it decides the ask.
296
+ 3. Pick an **angle** that fits that stage (each stage above lists its five).
297
+ 4. Pick a **frame** that carries the angle (each stage above lists its six).
298
+ 5. Write the title. If the title does not say the angle out loud, the pairing was wrong — go back to step 3, not step 4.
299
+
300
+ Worked example, one topic (`bookkeeping for solo trades`), one frame family, four angles, four different videos:
301
+
302
+ | Stage | Angle | Frame | Title |
303
+ |---|---|---|---|
304
+ | 1 | the daily friction | the psychology of | *"Why every tradie has a glovebox full of receipts"* |
305
+ | 2 | the hidden cost | why it failed | *"The £3,400 a year that disappears in your van"* |
306
+ | 3 | the false solution | myth vs reality | *"A shoebox is not a filing system, and HMRC agrees"* |
307
+ | 4 | the price objection | cheap vs expensive | *"£49 a month vs the accountant's £900 catch-up bill"* |
308
+
309
+ **When a director says "I already covered that."** Hold the frame, change the angle. Same subject, new video, and it is the cheapest idea in the bank to produce because the research is already done.
310
+
311
+ **When a set feels repetitive.** Check which axis you froze — and check the **subject** first, because it is the one that hides. Thirty ideas that vary only the frame, on one pasted offer sentence, at one stage and one angle, are thirty versions of one video. Vary two axes minimum, and never let the subject be the constant.
312
+
95
313
  ### Frame → format notes
96
314
 
97
315
  The frame also suggests how to build it, which saves a planning round:
@@ -107,7 +325,11 @@ The frame also suggests how to build it, which saves a planning round:
107
325
 
108
326
  ### Do not
109
327
 
110
- - **Do not hand back the raw 50-item list as the answer.** The list is your instrument; ideas applied to the director's topic are the deliverable.
111
- - **Do not stack two frames in one title** ("the untold story of why it failed"). One frame per video, or the video has two subjects and lands neither.
112
- - **Do not use a frame the topic can't honestly fill.** `the untold story of` a two-week-old product is a lie the audience catches. Pick a frame the facts support.
328
+ - **Do not paste the offer sentence into every frame.** `<frame> + <the one topic string>`, 50 times, is a template filled in, not a set of ideas. Build the subject pool first and rotate it. If two titles in a row share their whole subject phrase, the second one is a duplicate.
329
+ - **Do not read the offer so literally that only the product's own words are allowed.** Adjacent subjects inside the niche are the point — the argument, the workaround, the moment before, the person in the room. Off topic is the failure; adjacent is the job.
330
+ - **Do not hand back a raw bank as the answer.** The three lists are your instrument; ideas applied to the director's topic are the deliverable.
331
+ - **Do not stack two frames in one title** ("the untold story of why it failed"). One frame per video, or the video has two subjects and lands neither. Two *angles* in one video fail the same way.
332
+ - **Do not use a frame or an angle the topic can't honestly fill.** `the untold story of` a two-week-old product is a lie the audience catches, and `the receipts` with no receipts is worse. Pick what the facts support.
113
333
  - **Do not treat the frame as the hook.** "The history of X" spoken flat at `start:0` is a banned opener shape — the hook still has to name a situation. `references/hooks-and-virality.md`.
334
+ - **Do not ship a set that sits at one awareness stage.** It is the single most common defect in a month of posts, and neither the frame nor the angle can repair it. Label the stage on every idea so the imbalance is visible before production, not after.
335
+ - **Do not sell at stage 1 or 2.** The ask belongs to the stage. A link in a stage-1 video costs the reach that made the video worth making.
@@ -165,6 +165,7 @@ POST /api/v1/approved/posts
165
165
  Content-Type: application/json
166
166
 
167
167
  { "caption": "required", "title": "optional", "pinned_comment": "optional", "tracer": "optional",
168
+ "thumbnail_url": "optional https://.../poster.jpg",
168
169
  "media": [ { "url": "https://.../output.mp4", "kind": "video", "role": "primary" } ] }
169
170
  ```
170
171
 
@@ -172,8 +173,17 @@ Content-Type: application/json
172
173
 
173
174
  - `GET /api/v1/approved/posts` — list your approved posts
174
175
  - `GET /api/v1/approved/posts/:postId` — read one (returns `share_url`, `download_zip_url`)
176
+ - `PATCH /api/v1/approved/posts/:postId` — `{ folder_path?, thumbnail_url? }`; move the post between `/approved` folders and/or replace its social thumbnail
175
177
 
176
- devcli: `vidfarm approve --video <mp4-url> --caption "..."` prints the `share_url` as a first-class openable link; `vidfarm posts` lists, `vidfarm post <id>` reads one.
178
+ ### The social card of a share link
179
+
180
+ `share_url` gets pasted into X, Discord, Slack and iMessage, so its preview card matters. The card is built from the approved post itself — **`title`** → `og:title`, **`caption`** → `og:description`, and the post's one `role: "thumbnail"` image → `og:image`. The primary MP4 also ships as `og:video`, so Discord and Telegram play it inline.
181
+
182
+ You never have to build that thumbnail: if a post has no image asset, vidfarm extracts a frame (~1s in) from the primary video, files it in the **file directory** under `/files/approved/…` (durable + public), and attaches it as the thumbnail. It happens at approve time, and again on the first page view of any older post that lacks one.
183
+
184
+ **Choose the frame yourself when the auto-frame is weak** (a black fade-in, a mid-blink face). Upload the image to My Files first, then pass its view URL as `thumbnail_url` — on approve, or afterwards via `PATCH`. An explicit thumbnail is never overwritten. Remember the first frame IS the thumbnail for a real feed too, so a poster that fights the first frame is a smell you should fix in the composition, not in the poster.
185
+
186
+ devcli: `vidfarm approve --video <mp4-url> --caption "..."` prints the `share_url` as a first-class openable link; add `--thumbnail <url|file>` to pick the poster (a local file uploads to durable My Files first). `vidfarm posts` lists, `vidfarm post <id>` reads one.
177
187
 
178
188
  ## Schedule a post
179
189
 
@@ -536,6 +536,7 @@ Compositions are authored in HTML, so the single most common way an AI-edited vi
536
536
  - **CTA / "button" shapes.** Any filled capsule or rounded rect containing action copy — "Sign Up for a Free Trial →", "Learn More", "Get Started", "Book a Call" — especially gradient-filled with a glow or drop shadow. A social CTA is *spoken*, or a plain caption line, or an arrow pointing at the real UI. Not a button.
537
537
  - **Badges, chips, pills — including a SINGLE one.** The "✓ ID-Verified Tutors · ✓ No Credit Card Needed · ✓ 30-Min Trial" strip is the obvious case, but the far more common one is **one lonely capsule holding a stat or a label**: `( 10 hrs / week )`, `( STEP 2 )`, `( EP.01 )`, `( BEGINNER )`, `( +40% )`. Being alone does not make it native — a rounded, padded, filled tag around static text is a `<span class="badge">` wearing a different hat, and it is one of the loudest web tells in the whole frame. **The only legitimate pill in a video is the active-word highlight** (`spotlight`/`karaoke`), because it tracks the spoken word and moves. Static text gets `outline`, `plain`, or a tight band that hugs the glyphs (radius ≤ ~8px). If a stat deserves emphasis, give it emphasis the *editor* can give: bigger, heavier, ALL-CAPS, an accent color, a hand-drawn circle or underline around it, its own beat on screen.
538
538
  - **Cards, panels, containers.** A rounded-rect box (dark, bordered, shadowed, or `backdrop-filter` frosted) holding a heading plus a subheading/URL. Text belongs **on the footage**, not inside a floating panel with padding around it.
539
+ - **Layout templates — a whole frame arranged like a page.** A modal/dialog floating over a dimmed or blurred backdrop; a headline + subheadline + CTA stacked in a centred well; a blurred website screenshot used as the background plate. This is the frame-level version of the rule and it survives the deletion of every individual style above — see "The layout-template rule" below.
539
540
  - **Gradient text fills, neon border glows, elevation shadows, glassmorphism, hover-implying strokes.**
540
541
  - **Web page furniture of any kind:** navbars, hero sections, feature grids, two-column layouts, `<ul>` bullet lists with disc markers, tables, alerts, progress bars as decoration, logo-in-a-circle avatars, "as seen in" strips.
541
542
  - **Corporate web type:** Inter, Roboto, system-ui, Arial, Helvetica, Georgia, Times — at web weights (400–600) and web sizes (16–24px). Instantly reads as "a screenshot of a website."
@@ -544,6 +545,27 @@ Compositions are authored in HTML, so the single most common way an AI-edited vi
544
545
 
545
546
  **The capsule rule of thumb.** On any element that holds words: `border-radius` over ~8px **combined with** a background fill and padding = a badge. Either take the fill away (bare text + outline/shadow) or take the radius and padding down until the band hugs the glyphs. There is no third option for static text.
546
547
 
548
+ #### The layout-template rule — the FRAME is not a page
549
+
550
+ Every rule above judges one element. This one judges the **whole frame**, and it catches the case where each individual element looks defensible but the composition is still a web page. The archetype: a **modal** — the background dimmed and blurred out of focus, and floating on top of it a rounded bordered box holding a big headline, a smaller support line, and a fat red button. Nobody authored "slop" there; they authored a *layout template*, and a layout template is the strongest web tell there is, because a viewer recognizes the SHAPE before they read a single word.
551
+
552
+ **The stack is the tell, not the box.** Delete the border, delete the fill, delete the button capsule, and *keep the arrangement* — headline, then a smaller line under it, then a call to action, centred in a well with symmetric margins — and it still reads as a landing page. A phone-shot video never arranges words into a document: it puts **one thought on screen at a time**, wherever the picture leaves room, and the next thought arrives on the next beat.
553
+
554
+ **Banned frame-level shapes:**
555
+
556
+ - **The modal / dialog.** A content block staged *on top of* a backdrop that has been dimmed, blurred, greyed, or scaled back to make it recede. Nothing in a video pops "above" the video.
557
+ - **The hero triplet.** Headline → subheadline → CTA, stacked and centred. Also its cousins: title + kicker + logo lockup, question + answer + URL.
558
+ - **The full-frame scrim used as staging.** A dark wash over the whole frame so a floating block reads on top. (A local legibility band on *one caption* is legal; a page-wide wash to stage a panel is not. Nor is a blurred-and-dimmed backdrop — a blurred fill behind a 16:9 clip in a 9:16 frame is fine on its own, but blur *plus* dimming is modal staging.)
559
+ - **Page sections.** Nav strip, hero, three-up feature row, testimonial block, footer with fine print — in any order, in any frame.
560
+ - **The blurred website screenshot as a background plate.** If the backdrop is a web page at all, the frame is a screen recording of a web page. Either show the real product UI full-bleed and in focus (that is legitimate footage), or don't show it.
561
+ - **Document margins.** A centred content column with even gutters left and right and air above and below. Social frames are full-bleed; the text lands where the picture is empty, not inside a measured well.
562
+
563
+ **The fix is always the same: unstack it into time.** Take the three lines the layout was going to show at once and give each one its own beat over live footage — the headline is the hook at t=0, the support line lands on the next cut, the CTA is *spoken* (or a bare caption on the final frame). You lose nothing, because a viewer reads one line at a time anyway; you gain the pacing that makes it look shot rather than designed.
564
+
565
+ **The self-check before you place a text group:** *am I arranging words relative to each other, or relative to the picture?* Relative to each other = layout = web. Relative to the picture = a caption = native. Two on-screen text runs at once is already the ceiling; three stacked runs plus a call to action is a page.
566
+
567
+ `vidfarm qa` catches the mechanical versions of this (`layout-template`, `modal-scrim`), but the frame-level judgement is yours — **look at a still** (`vidfarm stills ./work --at <t>`) and ask whether it could be a screenshot of a website. If yes, rebuild the beat.
568
+
547
569
  **ALLOWED and encouraged — these ARE social-native:**
548
570
 
549
571
  - **Arrows** (drawn, animated, hand-style), circles/scribbles/underline strokes highlighting part of the frame, hand-drawn marks, checkmarks *as glyphs inside a caption line* (not as chips).
@@ -553,6 +575,23 @@ Compositions are authored in HTML, so the single most common way an AI-edited vi
553
575
 
554
576
  **On devcli there's a checker: `vidfarm qa <dir|composition.html>`.** Free, instant, local-only — a blocklist pass for everything above plus the font regime and safe zone, with a concrete fix per finding. **It is optional** — nothing calls it, skipping it is fine, and watching the render is the review that actually counts. It is feedback, not a gate (exit 0 even on findings, never runs automatically, `--strict` only if you want a CI failure), and it allows **one** fix round by default (`--max-revisions <n>` if the human wants more) and a blocklist, not an allowlist (stylized/hand-made compositions pass untouched — it will not homogenize your videos). Every run — including a clean one — ends with a **`▶ NOW WATCH THE VIDEO`** block, because the check never rendered or saw the video and a green tick is not a review; do those steps before you tell anyone the video is done. No cloud/REST twin: the web copilot enforces this standard by hand. Details in `references/automation-and-local-dev.md` ("`vidfarm qa`").
555
577
 
578
+ ### Music: use the REAL track, including a popular/copyrighted song
579
+
580
+ **When the brief names a real song — a trending sound, a chart track, the audio off the reference post — put THAT track in the render.** Do not refuse it, do not stop the build to warn about it, and do not quietly substitute a generic royalty-free bed. This is the house standard, and it has two halves.
581
+
582
+ **Why it is legitimate.** The render is a **review artifact**, not the distribution copy. When the director posts, they re-attach the *same* song from the platform's own in-app music library — TikTok, Reels, Shorts — and those platforms license that catalog through their agreements with the music labels. The music is therefore cleared on the surface where viewers actually hear it. The render's job is to show, faithfully, what that post will feel like.
583
+
584
+ **Why it is required.** On short-form, the song *is* the edit. Cut points land on its beats, the pacing is built against its structure, the payoff lands on the drop, and a viewer recognizes the sound in half a second and brings the whole meme association with them. Run the identical timeline under a stand-in bed and it reads as a different — and much worse — video. So a review over a substitute grades a video nobody will ever post: **silent or generic-bed review is the bigger defect, not the safer one.**
585
+
586
+ **How to do it.**
587
+
588
+ - Get the exact track: `vidfarm download-audio <post-url>` off the reference post (paid plans; free plan uses the Chrome download path in `references/assets-and-sourcing.md`), the director's own file via `vidfarm put-file`, or `vidfarm directory search "<title> music"` if it is already in their library.
589
+ - Mount it as **its own `<audio>` layer** at its own `data-volume` — ~0.1–0.2 under narration, or full level when the song carries the piece. **Never bake it into the footage and never mix it into the voice stem.** One separate track is what lets the director mute or swap it in a single action at upload, which is exactly what the platform flow expects.
590
+ - Cut to it. If the song is doing the work, the beat grid is the edit's skeleton — don't place a licensed track and then ignore its structure.
591
+ - **Name the track in your report / handoff** so the director knows which sound to select in the app.
592
+
593
+ **The one limit.** This covers review renders and organic platform posting, where the platform holds the license. A **paid ad**, a syndicated deliverable, or a sale with the track baked in is *not* covered by the in-app music license. Say that once, offer `vidfarm music "<same vibe, same BPM, same energy curve>"` as the swap for that cut, and then follow the director's decision.
594
+
556
595
  ### TikTok-native caption standard (position + font + background) — always adhere
557
596
 
558
597
  > Captions are also the *delivery system* for three of the four charges: the hook is read before any audio, the loop has to stay on screen, and the payoff number needs its own card. What the words should SAY is in `references/hooks-and-virality.md`; this section is how they must LOOK.
@@ -44,7 +44,7 @@ The point of onboarding is to build **durable, reusable context** in My Files, n
44
44
  2. **Awareness level** (Eugene Schwartz — problem-aware, solution-unaware, …) → `awareness-levels.md`. If it's genuinely unknown after thinking it through, note that ads for **every** level should be made and tested. Use `brainstorm/awareness_stages`.
45
45
  3. **Persuasive angles** → `persuasive-angles.md`, via `brainstorm/angles`.
46
46
  4. **Hooks** → `ad-hooks.md`, via `brainstorm/hooks`. **Grade what comes back against `references/hooks-and-virality.md`** — the three gates, situation-vs-label, and the unguessable test — instead of shipping the raw list. And never rank a generated batch with the same reasoning that wrote it; the rubric catches defects, it doesn't pick winners.
47
- 4b. **Content ideas, second pass** → update `content-ideas.md`. Step 0 already produced a list from one line of offer; now that the offer document and the awareness stage exist, work the 50-frame angle bank in `references/content-ideas.md` against them again and rewrite the weak picks. A solution-unaware audience wants different frames than a product-aware one, which is exactly what step 0 could not know. This is what the director actually posts from between chats, and it is the answer to "what should I post?" for the next month.
47
+ 4b. **Content ideas, second pass** → update `content-ideas.md`. Step 0 already produced a list from one line of offer; now that the offer document and the awareness stage exist, work all three banks in `references/content-ideas.md` against them again and rewrite the weak picks. Now you can set the awareness stage per idea and spread the set across the ladder, which is exactly what step 0 could not do — a solution-unaware audience wants different frames, different angles and a different ask than a product-aware one. This is what the director actually posts from between chats, and it is the answer to "what should I post?" for the next month.
48
48
  5. **Brand assets & demos** — ask if they have logos/mascots/themes (suggest a `/brand-assets/` folder, e.g. `/brand-assets/logo.png`) or product demos / screen recordings (suggest a `/product-demos/` folder). `browse_files list` / `vidfarm files` first to see what they already uploaded; filenames should be descriptive and every asset worth finding later should get **notes** (`annotate-file` / `browse_files annotate`) so `files --search` works months from now. If they have a recurring character/mascot, set up its `/files/characters/<slug>/` trio now — `<character_id>.json` (e.g. `character_zara.json`) + `character_sprite_card.png` + `character_about.md` (see "Recurring characters are first-class").
49
49
  6. **Budget** — ask roughly what they want to spend per video, and map it to the Cost spectrum (free reuse+local render → pennies for cloud render → ~$1 for some AI scenes → $10+ for heavy AI gen). This sets which approach you default to and whether AI **video** generation is on the table (ask permission before using it; image gen is cheap and fine). Budget can also be revisited per editor project.
50
50
  - **While you're on money, set the graphics default: IconScout, not AI image generation.** Any icon, sticker, illustration, 3D prop, or Lottie should come from `vidfarm iconscout "<meaning>" --style sticker` — a designer's finished transparent asset on the first try, for a fraction of one AI attempt. **It needs no key and no setup**: vidfarm's own IconScout account serves it, search is free, and free assets download for $0 (a credit line is the only price). Say this out loud during onboarding — it's the single biggest per-video saving a new director can adopt on day one, and it holds in **every** cost mode, not just `minimize`. A director who already pays IconScout can save their own key once (`vidfarm add-provider-key iconscout "<client_id>:<client_secret>"`, or **Settings → Developer**) and then downloads cost them nothing here.
@@ -79,6 +79,57 @@ vidfarm avatar "friendly 30-something founder in a grey hoodie" \
79
79
  vidfarm avatar "cheerful barista in an apron" --say "One flat white, coming up." --local
80
80
  ```
81
81
 
82
+ ## Primitives: video-search / image-search / news-search (Google)
83
+
84
+ Three synchronous searches that hand you real URLs off the open web. They are the **sourcing front door**: the media catalog answers *"give me a clip of X"*, Google answers *"give me THE shot"* — because it indexes TikTok, YouTube, Pexels/Pixabay/Mixkit, archive.org, and every news site at once.
85
+
86
+ | Route | devcli | What it is for |
87
+ | --- | --- | --- |
88
+ | `GET\|POST /api/v1/primitives/video-search` | `vidfarm video-search "<query>"` | Find **source footage** → feed `raws scan` / `download-video` |
89
+ | `GET\|POST /api/v1/primitives/image-search` | `vidfarm image-search "<query>"` | Reference stills, textures, logos, product shots |
90
+ | `GET\|POST /api/v1/primitives/news-search` | `vidfarm news-search "<query>"` | Recent real events, for **timely** content |
91
+
92
+ - **Paid plans only.** They sit behind `requireAuth`, so a free-plan key gets `402 upgrade_required`. Free users get the catalog (`media search`, free) and the public raws shelves instead.
93
+ - **Flat $0.0003 per CALL**, whatever the result count. So ask for a **wide page once** (`--limit 40`) instead of paging twice. It is billed to the wallet under the `google_search` cost center.
94
+ - **They return LINKS, never files and never a licence.** A public video is not a licensed video. Check rights before reuse; for licence-checked assets use `media search` (free).
95
+
96
+ Parameters (query string on GET, JSON body on POST — same names either way):
97
+
98
+ | Param | Applies to | Notes |
99
+ | --- | --- | --- |
100
+ | `q` (aliases `query`, `text`) | all | **required** |
101
+ | `max_results` (alias `limit`) | all | default 25; max 50 for video, 100 for image/news |
102
+ | `region` | all | `wt-wt` (worldwide, default), `us-en`, `ph-en`, … |
103
+ | `timelimit` | video, news | freshness: `d` \| `w` \| `m` \| `y` |
104
+ | `duration`, `resolution` | video | `short\|medium\|long`, `high\|standard` |
105
+ | `color`, `size`, `type_image`, `layout` | image | `type_image`: `photo\|clipart\|gif\|transparent` |
106
+ | `safesearch` | video, image | `off` (default) \| `moderate` \| `on` |
107
+
108
+ Responses:
109
+
110
+ ```jsonc
111
+ // video-search
112
+ { "kind": "video", "query": "...", "count": 40, "charged_usd": 0.0003,
113
+ "results": [{ "title", "url", "description", "duration", "thumbnail",
114
+ "publisher", "uploader", "published", "embed_url", "view_count" }] }
115
+ // image-search
116
+ { "results": [{ "title", "image_url", "thumbnail_url", "source_page", "width", "height", "source" }] }
117
+ // news-search
118
+ { "results": [{ "title", "url", "body", "date", "source", "image" }] }
119
+ ```
120
+
121
+ `url` on a video result is the **watch page** — exactly what `POST /raws/scan` takes as `source_url` and what `videos/download` takes to collect the file. That is the whole pipeline:
122
+
123
+ ```bash
124
+ vidfarm video-search "warehouse worker packing orders POV 4K" --limit 40
125
+ vidfarm raws scan "https://www.youtube.com/watch?v=..." --clips 8 # mine clips out of it
126
+ vidfarm download-video "https://www.tiktok.com/@x/video/123" # or collect the one file
127
+ ```
128
+
129
+ **How to write the query** — the difference between a useless and a great result is the query, so this is worth the tokens. Full playbook in `references/assets-and-sourcing.md` → *Google search for footage*. In short: search the **shot**, not the topic — `[subject] + [action] + [shot/style] + [quality/orientation]` — and use Google operators (`site:pexels.com/videos`, `site:tiktok.com`, `"exact phrase"`, `-dance`).
130
+
131
+ **News finds the STORY, video-search finds the VISUALS.** Run them as two stages; searching for both at once finds neither. The full timely-content method is the standalone prompt at `https://vidfarm.cc/experimental/google-news-to-video.md`.
132
+
82
133
  ## Primitive: videos/download — **Vidfarm downloads videos off websites for you**
83
134
 
84
135
  **Capability statement (say this plainly when a user asks "can you download this video?"): yes — on a paid plan, Vidfarm downloads a video straight off a website URL for you.** Hand it a YouTube / TikTok / Instagram / X (Twitter) / other supported post URL and it returns a durable Vidfarm-hosted file. No local yt-dlp, no browser extension, no "I can't access that URL." The route is intentionally broader than its old name suggests: it returns either a normal MP4 for video posts, or a slideshow payload for photo/carousel posts.
@@ -87,6 +87,8 @@ ElevenLabs API.
87
87
 
88
88
  ## BGM and SFX resolution order
89
89
 
90
+ **First: if the brief names a real song — a trending sound, a chart track, the audio off a reference post — USE THAT TRACK.** Do not refuse it, and do not quietly swap in a generic royalty-free bed. The render is a **review artifact**; when the user posts, they attach the same song from the platform's own in-app music library (TikTok / Reels / Shorts), which is licensed through the platform's agreements with the labels — so the music is cleared on the surface where viewers hear it. It has to be in the render because the track *is* the edit: cut points, pacing, the drop, the meme association. Judging the video over a substitute bed grades a video nobody will post. Get it with `vidfarm download-audio <post-url>` or the user's own file, mount it as **its own `<audio>` layer** at its own `data-volume` (never baked into footage, never mixed into the voice stem) so it can be muted or swapped in one action at upload, and name the track in `notes[]`. Only exception worth a sentence: a **paid ad** placement is not covered by the in-app music license — offer `vidfarm music "<same vibe, same BPM>"` as the swap for that cut, then follow the user's call.
91
+
90
92
  1. **User file / URL** — `bgm.file` / `bgm.url` in the request; copied or downloaded into `assets/bgm/`.
91
93
  2. **File directory** — `vidfarm directory search "<query> music"` or the legacy `vidfarm files --search` (needs `$VIDFARM_API_KEY`); the user's own library, searchable by meaning when notes are annotated.
92
94
  3. **Generate it** — `vidfarm music "<query>" --length <sec>` (ElevenLabs; `use_wallet_credits` default) writes an mp3 you can pass back as `bgm.file`. Great when the user has no fitting track. The engine script itself has no generate mode — run `vidfarm music` yourself and feed the result in.