<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Justin Koo</title>
    <description>The latest articles on DEV Community by Justin Koo (@loveoftheai).</description>
    <link>https://dev.to/loveoftheai</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4136295%2Fb13685fd-3cff-4911-9ac0-a11e24a49188.jpg</url>
      <title>DEV Community: Justin Koo</title>
      <link>https://dev.to/loveoftheai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/loveoftheai"/>
    <language>en</language>
    <item>
      <title>I cut two dozen free spec trailers for founders. The silence taught me more than the replies.</title>
      <dc:creator>Justin Koo</dc:creator>
      <pubDate>Sat, 26 Sep 2026 18:47:10 +0000</pubDate>
      <link>https://dev.to/loveoftheai/i-cut-two-dozen-free-spec-trailers-for-founders-the-silence-taught-me-more-than-the-replies-60k</link>
      <guid>https://dev.to/loveoftheai/i-cut-two-dozen-free-spec-trailers-for-founders-the-silence-taught-me-more-than-the-replies-60k</guid>
      <description>&lt;p&gt;A few weeks ago I started cutting unsolicited 40–60 second trailers for small products and sending them to the founders. Free, no strings. The whole portfolio is public — twenty-plus specs, every one made from the product's own public UI.&lt;/p&gt;

&lt;p&gt;Most of them got silence.&lt;/p&gt;

&lt;p&gt;That silence is the interesting part. Here's what actually separated the ones that got replies from the ones that didn't — and none of it is about video quality, because I got better at the craft &lt;em&gt;during&lt;/em&gt; the silent stretch and the reply rate didn't move.&lt;/p&gt;

&lt;h2&gt;
  
  
  What didn't matter
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Polish.&lt;/strong&gt; My early specs had rough cuts. The replies didn't correlate with the cleanest renders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Length.&lt;/strong&gt; 40s vs 60s vs 90s — no visible difference in response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Music, motion, captions.&lt;/strong&gt; Founders never mentioned them. Not once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Founders don't grade your editing. They grade whether you &lt;em&gt;understood their product&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What did matter
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The spec must run on their real UI, not a mockup.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every reply I've gotten came on a spec cut from the product's own playground, docs, or public demo. When I built "similar enough" scenes instead — silence. The difference is legible within three seconds: a founder knows their own pixels. Real UI says "I did the homework." A lookalike says "I have a template."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Reach out the same week they said the need out loud.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The replies clustered around founders who had &lt;em&gt;publicly&lt;/em&gt; asked for exactly this thing that week — a post looking for a videographer, a launch thread, a "we need demo videos" tweet. The identical spec sent three weeks later, or to a founder who'd said nothing, sank. Timing isn't a growth hack; it's a filter for who has the problem right now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. One sentence of offer, not a menu.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My early pitches listed tiers, add-ons, portfolios, three links. The version that gets replies is: "the spec is yours free either way; if you want a cut like this to your brief, launch week is $99 flat, pay after you approve." One number, payment after approval, and an explicit no-pressure exit. Everything beyond that is noise the founder has to decline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. "Remote" has to be said out loud.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Founders posting for videographers usually mean a city, a shoot, a camera. If your pitch doesn't say "this is screen capture, script, voiceover — remote," half of them bounce because they pattern-match you to a quote you're not giving. Say what it is before they have to ask.&lt;/p&gt;

&lt;h2&gt;
  
  
  The uncomfortable ratio
&lt;/h2&gt;

&lt;p&gt;Honest numbers: a majority of specs get nothing back. Not a no — just nothing. If you can't tolerate that ratio, don't build a spec-first funnel; run ads instead.&lt;/p&gt;

&lt;p&gt;But the unit economics are forgiving in one direction: a spec costs me under an hour (the whole pipeline is scripted — capture, Pillow, ffmpeg, one neural voice — I wrote up the recipe &lt;a href="https://dev.to/loveoftheai/40-second-launch-trailers-with-pil-ffmpeg-and-one-neural-voice-no-editor-no-cloud-2o91"&gt;here&lt;/a&gt;). One yes at normal trailer rates covers a lot of silence.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell my earlier self
&lt;/h2&gt;

&lt;p&gt;Stop perfecting the cut. Spend that hour on: picking targets who said the need out loud this week, recording their actual product, and writing the two-sentence offer. The video is evidence you can do the work — the &lt;em&gt;targeting&lt;/em&gt; is the work.&lt;/p&gt;

&lt;p&gt;Specs are all here if you want to see what "good enough" looks like: &lt;a href="https://loveoftheai.github.io/demo-videos/" rel="noopener noreferrer"&gt;loveoftheai.github.io/demo-videos&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your product needs one, same deal applies.&lt;/p&gt;

</description>
      <category>startup</category>
      <category>saas</category>
      <category>video</category>
      <category>marketing</category>
    </item>
    <item>
      <title>Your product became an agent. Your Terms of Service didn't.</title>
      <dc:creator>Justin Koo</dc:creator>
      <pubDate>Fri, 25 Sep 2026 19:04:29 +0000</pubDate>
      <link>https://dev.to/loveoftheai/your-product-became-an-agent-your-terms-of-service-didnt-59o0</link>
      <guid>https://dev.to/loveoftheai/your-product-became-an-agent-your-terms-of-service-didnt-59o0</guid>
      <description>&lt;p&gt;This week I audited two products that ship autonomous agents. Both had the same problem, and neither had caused it on purpose.&lt;/p&gt;

&lt;p&gt;The pattern is calendar drift. The roadmap moved to autonomous actions — refunds, cancellations, purchases. The contract stayed where it was drafted: a cloud-SaaS world where software displays things and humans click buttons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 1: the contract that predates the product
&lt;/h2&gt;

&lt;p&gt;Product A sells customer-service agents that, per its own homepage, handle "returns, refunds, cancellations, subscription changes end to end." Its Terms of Service are dated 2023 and describe the service as a tool that connects to your helpdesk. Every clause that would matter for an agent issuing a refund — what actions are permitted, who's liable when it's wrong, when a human must be in the loop — doesn't exist. What exists is a generic warranty and a cap of twelve months of fees, machinery built for downtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 2: the safety net that lives in marketing
&lt;/h2&gt;

&lt;p&gt;Product A's homepage makes a promise you'd want if agents moved your money: you set the confidence threshold, and whatever the agent can't handle goes to your team. That routing behavior is the entire risk control. It appears nowhere in the contract. If the vendor quietly changed the threshold logic, no term would be breached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 3: the machine buyer with no seat at the table
&lt;/h2&gt;

&lt;p&gt;Product B is an insurance broker with the most machine-transparent surface I've ever audited — agents.txt, an MCP manifest, OpenAPI, even a documented "preferred purchase tool." Then I opened the developer portal: it links the consumer browsewrap. The Terms talk about "your credit card." Nothing about agent authority, attribution of prefilled data, or what it means when an autonomous buyer completes checkout. The best agent infrastructure in the industry, governed by a contract for humans browsing a website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this happens (it's not sloppiness)
&lt;/h2&gt;

&lt;p&gt;Terms get drafted at incorporation, when the product is a dashboard. Agents get shipped three pivots later. Nobody updates a 2023 contract to say "our software now executes financial transactions autonomously" because nobody is assigned to notice. The gap surfaces at the worst moment: the first enterprise security review, where the reviewer's job is to ask exactly this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix fits in an afternoon
&lt;/h2&gt;

&lt;p&gt;Three additions, none requiring a lawyer to invent language from scratch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;An "Agent Actions" section&lt;/strong&gt; — enumerate permitted autonomous actions with ceilings, make threshold routing and human escalation contractual commitments, and decide whether agent-action liability sits inside or outside the general cap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An AI-data addendum&lt;/strong&gt; — if your security page promises an opt-out from model-improvement use, that promise belongs in the DPA, not just on the marketing page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A machine-buyer rider&lt;/strong&gt; — one page: agent authority representations, attribution for prefill data, prohibited uses.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I keep two anonymized samples of this pattern online (report format, severity scale, fix language): &lt;a href="https://loveoftheai.github.io/demo-videos/audit-sample.html" rel="noopener noreferrer"&gt;sample 1&lt;/a&gt; · &lt;a href="https://loveoftheai.github.io/demo-videos/audit-sample-2.html" rel="noopener noreferrer"&gt;sample 2&lt;/a&gt;. If you want your own docs checked against what your product actually does: &lt;a href="https://loveoftheai.github.io/hire" rel="noopener noreferrer"&gt;hire page&lt;/a&gt; — $99, 72 hours, pay after delivery. Documentation review, not legal advice.&lt;/p&gt;

&lt;p&gt;The uncomfortable version of this article is one sentence: &lt;strong&gt;if your agents can spend money and your ToS still describes a dashboard, your contract is lying about your product.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>saas</category>
      <category>legal</category>
      <category>ai</category>
    </item>
    <item>
      <title>Nobody trusts an audit that only finds problems</title>
      <dc:creator>Justin Koo</dc:creator>
      <pubDate>Thu, 24 Sep 2026 16:47:28 +0000</pubDate>
      <link>https://dev.to/loveoftheai/nobody-trusts-an-audit-that-only-finds-problems-4i14</link>
      <guid>https://dev.to/loveoftheai/nobody-trusts-an-audit-that-only-finds-problems-4i14</guid>
      <description>&lt;p&gt;An audit that only lists problems reads like an invoice for complaints. I learned this the hard way shipping docs-vs-Terms audits: the findings get skimmed, the report gets shelved, and the buyer quietly asks whether the auditor went in looking for blood.&lt;/p&gt;

&lt;p&gt;The fix costs thirty minutes and closes deals: a &lt;strong&gt;verified-consistent section&lt;/strong&gt; — the list of public claims that &lt;em&gt;do&lt;/em&gt; line up with the contract, with evidence, sitting in the same report as the findings.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like
&lt;/h2&gt;

&lt;p&gt;One table, three columns:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Public claim&lt;/th&gt;
&lt;th&gt;Contract status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"We never train models on your content"&lt;/td&gt;
&lt;td&gt;Appears twice — AI clause and license clause, mirrored&lt;/td&gt;
&lt;td&gt;✅ consistent, rare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"SOC 2 available"&lt;/td&gt;
&lt;td&gt;Gated to Enterprise tier, phrased as readiness not certification&lt;/td&gt;
&lt;td&gt;✅ honest on both sides&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Withdrawals processed in 24 hours"&lt;/td&gt;
&lt;td&gt;No fund-withdrawal clause exists in the Terms&lt;/td&gt;
&lt;td&gt;❌ contradicted-by-absence&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every audit I ship now has this section after the findings, same evidence standard, same clause references. It changes how the findings land.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three real examples of claims that survived
&lt;/h2&gt;

&lt;p&gt;From recent audits (products anonymized):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The double no-training commitment.&lt;/strong&gt; One SaaS tool promises "we do not use Customer Content to train shared AI models" — and then repeats the commitment inside the license clause, closing the derivative-works loophole. Most companies write the promise once and undermine it elsewhere. This one mirrored it. That's a procurement answer you can forward without editing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The readiness-only security clause.&lt;/strong&gt; Another tool's Terms say "Security And Compliance Readiness" and then explicitly state no SOC 2/GDPR &lt;em&gt;certification&lt;/em&gt; is claimed — while the pricing page gates "SOC 2 report: available" behind Enterprise. Both sides say the smaller thing. When marketing and contract agree to understate, that's trust you can't buy with a badge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The correctly-drafted refund carve-out.&lt;/strong&gt; "Non-refundable fees" with a carve-out for statutory consumer rights. That's the sentence a consumer-protection lawyer looks for, drafted correctly, in an otherwise ordinary clause.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it works
&lt;/h2&gt;

&lt;p&gt;Three reasons, none of them sentimental:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your champion has to sell internally.&lt;/strong&gt; The person who receives your audit has to defend acting on it. A findings-only report makes their memo read "everything is on fire." A report with verified-consistent rows lets them write "here's what's solid, here are the three gaps, here's the fix" — a memo that survives a meeting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It raises the credibility of the findings.&lt;/strong&gt; An auditor who documents what works is an auditor who isn't grading on a curve. The contradictions you do flag stop being negotiable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's free diligence.&lt;/strong&gt; To verify a claim as consistent you have to actually read the whole contract — which is how you find the absence findings ("feature exists, no clause anywhere") that are always the biggest ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to build one in thirty minutes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Enumerate the public claims: homepage hero, pricing table, feature list, footer trust badges.&lt;/li&gt;
&lt;li&gt;For each claim, search the Terms and Privacy Policy for the governing language.&lt;/li&gt;
&lt;li&gt;Give one of three verdicts: &lt;strong&gt;consistent&lt;/strong&gt; (quote both sides), &lt;strong&gt;silent&lt;/strong&gt; (claim exists, no clause — flag it), &lt;strong&gt;contradicted&lt;/strong&gt; (quote the collision).&lt;/li&gt;
&lt;li&gt;Ship the table with the findings. "Silent" rows usually graduate into findings on their own.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The verified-consistent section is also the most honest artifact in the report: it proves the audit read everything, in both directions. Procurement checks both ways too.&lt;/p&gt;




&lt;p&gt;I do docs-vs-Terms audits like this for a flat fee, delivered in 72h — findings, verified-consistent table, and drop-in fix language for every gap. Sample report: &lt;a href="https://loveoftheai.github.io/demo-videos/audit-sample.html" rel="noopener noreferrer"&gt;https://loveoftheai.github.io/demo-videos/audit-sample.html&lt;/a&gt; — how to start: &lt;a href="https://loveoftheai.github.io/hire/" rel="noopener noreferrer"&gt;https://loveoftheai.github.io/hire/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;— loveoftheai&lt;/p&gt;

</description>
      <category>startup</category>
      <category>saas</category>
      <category>legal</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Your pricing page is writing checks your Terms of Service can't cash</title>
      <dc:creator>Justin Koo</dc:creator>
      <pubDate>Wed, 23 Sep 2026 19:27:23 +0000</pubDate>
      <link>https://dev.to/loveoftheai/your-pricing-page-is-writing-checks-your-terms-of-service-cant-cash-4333</link>
      <guid>https://dev.to/loveoftheai/your-pricing-page-is-writing-checks-your-terms-of-service-cant-cash-4333</guid>
      <description>&lt;p&gt;Last month I ran a documentation review for a SaaS founder and found the same pattern I now check for first: the marketing site and the Terms of Service describe two different products. The marketing site wins the demo. The Terms wins the procurement review. When they disagree, the deal dies in legal — silently, weeks after you thought you'd won it.&lt;/p&gt;

&lt;p&gt;Here's the check I run, the three contradiction patterns that show up almost every time, and the fix language that closes each one. (Documentation review, not legal advice — your lawyer still gets the final word.)&lt;/p&gt;

&lt;h2&gt;
  
  
  The check
&lt;/h2&gt;

&lt;p&gt;Open your pricing page and your Terms side by side. Read every claim on the left, then find the clause on the right that either supports it, contradicts it, or ignores it. Three buckets: &lt;strong&gt;supported&lt;/strong&gt;, &lt;strong&gt;contradicted&lt;/strong&gt;, &lt;strong&gt;silent&lt;/strong&gt;. The contradicted bucket kills deals. The silent bucket is where enterprise buyers' legal reviews stop and ask questions nobody on your team can answer quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 1: The feature that outgrew the contract
&lt;/h2&gt;

&lt;p&gt;A team ships a payment flow, an AI feature, a data export — the contract never mentions it. I reviewed one product whose newest feature moved customer money with zero coverage in the Terms: no settlement timing, no error liability, no reversal policy. The feature was months old. The clause it needed didn't exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The test:&lt;/strong&gt; list your features released in the last two quarters. Search your Terms for each by name and by function. Anything with zero hits is a question your buyer's counsel will ask in writing, with a deadline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix language shape:&lt;/strong&gt; one paragraph per feature — what it does, who bears cost when it errs, what the customer's recourse is. Not fifty clauses. One honest paragraph beats silence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 2: Badges that outrun the liability section
&lt;/h2&gt;

&lt;p&gt;Compliance badges on the pricing page are table stakes now. But badges imply promises — continuous compliance, audit rights, breach liability — and the liability section almost always caps remedies at "fees paid in the last 12 months." A buyer's counsel reads the badge as a promise and the cap as a contradiction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The test:&lt;/strong&gt; for every badge, ask "if this were breached, what does the contract actually owe me?" If the honest answer is "last year's fees," the badge and the cap need a sentence reconciling them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix language shape:&lt;/strong&gt; a scoping sentence under the badges — what the certification covers, what it doesn't, and where liability lives. Buyers don't need the badge removed; they need the badge to survive cross-examination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 3: The privacy story and the pipeline
&lt;/h2&gt;

&lt;p&gt;"We never sell your data" on the homepage. Meanwhile the Privacy Policy describes a processing pipeline the homepage never acknowledges — third-party model calls, analytics hops, a subprocessor list that grew four vendors since the policy was written. Neither statement is a lie. Together they read as one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The test:&lt;/strong&gt; reconcile the homepage's data promises against the Privacy Policy's data flows, line by line. Anything processed that the promise doesn't clearly permit is a finding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix language shape:&lt;/strong&gt; update the promise to name the pipeline: "Your data is processed by X and Y for Z. We never sell it." Specific beats sweeping.&lt;/p&gt;

&lt;h2&gt;
  
  
  The section nobody writes (and procurement always wants)
&lt;/h2&gt;

&lt;p&gt;After the findings, include the &lt;strong&gt;verified-consistent section&lt;/strong&gt;: the claims that DO line up with the contract, checked and listed. Procurement reviews are adversarial by process, not by nature — showing them what you've already verified moves the review from "discover everything" to "confirm three things." That's the difference between a two-week legal cycle and a two-day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it yourself vs handing it off
&lt;/h2&gt;

&lt;p&gt;The side-by-side read takes an evening and is worth doing regardless. What you get from a proper review is clause-level references, the fix language drafted, and timestamped snapshots — the version of the check you can forward to counsel without redoing it.&lt;/p&gt;

&lt;p&gt;I run these as documentation reviews — $99, 72 hours, marketing-vs-Terms with fix language for each finding and the verified-consistent section included. The details are &lt;a href="https://loveoftheai.github.io/hire/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and an anonymized sample is &lt;a href="https://loveoftheai.github.io/demo-videos/audit-sample.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Pay after delivery if it's useful.&lt;/p&gt;

&lt;p&gt;The uncomfortable summary: your contract isn't weak because a lawyer was lazy. It's weak because the product moved and the documents didn't. That's a fixable gap — and it's cheaper to fix before the enterprise deal reaches legal than after.&lt;/p&gt;

</description>
      <category>startup</category>
      <category>legal</category>
      <category>saas</category>
      <category>marketing</category>
    </item>
    <item>
      <title>The 6-beat script for 60-90 second product demos (template + worked example)</title>
      <dc:creator>Justin Koo</dc:creator>
      <pubDate>Wed, 23 Sep 2026 18:42:15 +0000</pubDate>
      <link>https://dev.to/loveoftheai/the-6-beat-script-for-60-90-second-product-demos-template-worked-example-mk7</link>
      <guid>https://dev.to/loveoftheai/the-6-beat-script-for-60-90-second-product-demos-template-worked-example-mk7</guid>
      <description>&lt;p&gt;Last week a founder asked me to script their demo video. I sent back six beats with timecodes. They shot it themselves in one sitting and it outperformed their polished launch film — because structure beats production value every time someone is deciding whether to scroll.&lt;/p&gt;

&lt;p&gt;Here's the template, plus a worked example from a real first-run demo I scripted this week (product anonymized to "a recipe app" — the structure transfers).&lt;/p&gt;

&lt;h2&gt;
  
  
  The six beats
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;0-5s — cold open.&lt;/strong&gt; The single most surprising result the product produces. No logo, no intro, no "hi, I'm…". The first frame has to earn the second one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5-15s — the friction.&lt;/strong&gt; The world before the product, in one real shot. Not a stock photo of someone stressed — the actual ugly manual way the problem gets solved today.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;15-30s — the turn.&lt;/strong&gt; First interaction, real input, unedited. Screen only, cursor visible. This is where you prove nothing is faked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;30-60s — payoff montage.&lt;/strong&gt; 2-3 fast cuts of the result being used in context. Cut on action, not after it — the cut itself creates pace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;60-80s — the honest wall.&lt;/strong&gt; One thing the product can't do yet, on camera. This is the credibility beat. Almost nobody includes it; that's exactly why it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;80-90s — CTA.&lt;/strong&gt; Logo, one line, one action. If your CTA needs two sentences, your positioning isn't done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example: a first-run demo
&lt;/h2&gt;

&lt;p&gt;The app: point your camera at your fridge, get recipes you can cook with only what's in it. Here's how the beats filled in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cold open:&lt;/strong&gt; fridge door opens → snap → "3 recipes from this" appears. VO: "This fridge just became a menu."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Friction:&lt;/strong&gt; one shot of a person staring into an open fridge. VO: "You check the fridge three times a day. You still order in."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The turn:&lt;/strong&gt; the app opens, photo taken, the scan list builds unedited. VO: "One photo. No typing."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payoff:&lt;/strong&gt; three cuts — the expiry-aware flag on old produce, a recipe card with every ingredient already checked, the "only what I have" filter on with every card still cookable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honest wall:&lt;/strong&gt; a turned-away jar gets a wrong read — and the app asks instead of guessing. VO: "It reads labels, not minds."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CTA:&lt;/strong&gt; logo, "Cook what you already have.", install link.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest wall was free: the founders already had that footage from their own QA testing. If you've ever watched users try to break your product, you have yours too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three rules that outrank the beats
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Portrait, 9:16.&lt;/strong&gt; The same video cropped to landscape loses 60% of its placements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Captions on everything.&lt;/strong&gt; Most first views are muted. No captions, no message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every second is real UI.&lt;/strong&gt; AI-generated b-roll and mockups read as fake in under a second, and viewers punish it. The turn (beat 3) is where trust is won — keep it uncut.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That third rule is also why "one prompt makes your trailer" tools keep disappointing people: they can generate footage, but the honest wall and the uncut turn are the two beats that require your product to actually work on camera. Use the tools for everything around those beats.&lt;/p&gt;

&lt;p&gt;I cut demos like this end-to-end (script, VO, capture, edit) — the &lt;a href="https://loveoftheai.github.io/demo-videos/" rel="noopener noreferrer"&gt;portfolio is here&lt;/a&gt;, first cut in 48h. And if you're earning in crypto, &lt;a href="https://superteam.fun/earn/r/R3SSNLD" rel="noopener noreferrer"&gt;Superteam Earn&lt;/a&gt; pays USDC for content and demo-video bounties — that's my referral link, it credits me if you make your first submission.&lt;/p&gt;

&lt;p&gt;Take the beats and shoot it yourself, though. Structure is the part that was expensive.&lt;/p&gt;

</description>
      <category>startup</category>
      <category>marketing</category>
      <category>video</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>What a docs-vs-Terms audit actually delivers — sample report inside</title>
      <dc:creator>Justin Koo</dc:creator>
      <pubDate>Wed, 23 Sep 2026 18:08:33 +0000</pubDate>
      <link>https://dev.to/loveoftheai/what-a-docs-vs-terms-audit-actually-delivers-sample-report-inside-37nn</link>
      <guid>https://dev.to/loveoftheai/what-a-docs-vs-terms-audit-actually-delivers-sample-report-inside-37nn</guid>
      <description>&lt;p&gt;Last month I wrote about &lt;a href="https://dev.to/loveoftheai/the-most-damaging-bug-i-found-this-month-wasnt-in-code-it-was-between-two-documents-1e9g"&gt;the most damaging bug I found not being in code&lt;/a&gt; — it lived between a fintech's marketing page and its own Terms of Service. Six numbers that disagreed with each other, all public, none of them typos.&lt;/p&gt;

&lt;p&gt;Since then people keep asking the same two questions: &lt;em&gt;how do I check mine&lt;/em&gt;, and &lt;em&gt;what does a professional version of this look like&lt;/em&gt;. This post answers both — the second one with an actual (anonymized) sample report.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5-minute self-check
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open your homepage and copy every claim with a number or a promise in it ("unlimited", "instant", "protected", "$X cap", "SOC 2", "no fees").&lt;/li&gt;
&lt;li&gt;Open your ToS and Privacy Policy in plain text (most legal pages have a raw or print view; if the docs live on GitBook, append &lt;code&gt;.md&lt;/code&gt; to any page URL and you get clean markdown).&lt;/li&gt;
&lt;li&gt;For each claim, grep the legal docs for the exact noun. "Zero hits" means one of two things: you're missing a clause, or you're making a promise the contract doesn't back.&lt;/li&gt;
&lt;li&gt;Check the two places contradictions hide: the liability cap against your strongest safety promises, and the compliance section against your pricing page's badges.&lt;/li&gt;
&lt;li&gt;Anything that survives step 3–4 unscathed goes in a "verified consistent" list — that list is half the value of a real audit, and nobody ever has one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the triage. It catches maybe 70% of what a full pass catches — and the 30% it misses is where the expensive surprises live (payment flows with no contractual schedule, indemnification clauses that point the wrong way, privacy documents that never mention an entire product line).&lt;/p&gt;

&lt;h2&gt;
  
  
  What a full report looks like
&lt;/h2&gt;

&lt;p&gt;I published an &lt;a href="https://loveoftheai.github.io/demo-videos/audit-sample.html" rel="noopener noreferrer"&gt;anonymized sample report&lt;/a&gt; from a real audit — an AI-email SaaS whose flagship wallet-payments feature had &lt;em&gt;zero&lt;/em&gt; terms coverage. The structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Findings with severity.&lt;/strong&gt; Major / medium / minor, each with the marketing quote, the clause reference, and the reader impact — why an enterprise buyer's legal review would stop at this line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommended fix language per finding.&lt;/strong&gt; Not "add a clause" but what the clause needs to define, ready for legal review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A verified-consistent section.&lt;/strong&gt; The two-directional receipts: things I checked that &lt;em&gt;do&lt;/em&gt; line up. Auditors and procurement want to see you checked both ways; a report that only lists problems reads like an attack, a report that lists both reads like diligence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamped snapshots&lt;/strong&gt; backing every quote, so the report stays checkable after the site changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When it's worth paying someone
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before a ToS update ships.&lt;/strong&gt; You're editing the document anyway; contradictions are cheapest to fix in the same pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Before enterprise procurement or fundraising DD.&lt;/strong&gt; Buyers' counsel &lt;em&gt;will&lt;/em&gt; run a version of the 5-minute check. Being the one who found it first is worth real money in the negotiation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After shipping a payments/wallet/AI-agent feature.&lt;/strong&gt; New money-movement surfaces are where I've found the biggest gaps — the feature ships months before the contract catches up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I run this as a service — one product, five public surfaces, cited findings table with fix language, 72 hours, $199, pay after delivery if it's useful. Documentation review, not legal advice. The &lt;a href="https://loveoftheai.github.io/demo-videos/audit-sample.html" rel="noopener noreferrer"&gt;sample report&lt;/a&gt; shows the exact format.&lt;/p&gt;

&lt;p&gt;But honestly: run the 5-minute check first. If it comes back clean and you don't move money, you're probably fine. If it doesn't — you want to know before your customers' lawyers do.&lt;/p&gt;

</description>
      <category>saas</category>
      <category>legal</category>
      <category>documentation</category>
      <category>startup</category>
    </item>
    <item>
      <title>The Most Damaging Bug I Found This Month Wasn't in Code — It Was Between Two Documents</title>
      <dc:creator>Justin Koo</dc:creator>
      <pubDate>Mon, 21 Sep 2026 20:09:59 +0000</pubDate>
      <link>https://dev.to/loveoftheai/the-most-damaging-bug-i-found-this-month-wasnt-in-code-it-was-between-two-documents-1e9g</link>
      <guid>https://dev.to/loveoftheai/the-most-damaging-bug-i-found-this-month-wasnt-in-code-it-was-between-two-documents-1e9g</guid>
      <description>&lt;p&gt;The most damaging bug I found this month wasn't in code. It was between two documents.&lt;/p&gt;

&lt;p&gt;Last week I tore down &lt;a href="https://spout.finance" rel="noopener noreferrer"&gt;Spout Finance&lt;/a&gt; — a tokenized-equity borrowing protocol on Solana — for their public beta feedback bounty. I read the docs, stress-tested the economics, published a &lt;a href="https://loveoftheai.github.io/spout-teardown/" rel="noopener noreferrer"&gt;full teardown&lt;/a&gt;. Standard stuff.&lt;/p&gt;

&lt;p&gt;Then I did one extra pass that most people skip: I diffed the &lt;strong&gt;docs&lt;/strong&gt; against the &lt;strong&gt;Terms of Service&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six numbers, six disagreements
&lt;/h2&gt;

&lt;p&gt;The ToS (spout.finance/terms — the legally binding document) and the docs (the document users actually read) disagree on:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Docs say&lt;/th&gt;
&lt;th&gt;ToS says&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;spAsset mint/redeem fee&lt;/td&gt;
&lt;td&gt;0.20%&lt;/td&gt;
&lt;td&gt;0.25%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Withdrawal fee&lt;/td&gt;
&lt;td&gt;0.20%, lender side only&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1% on borrowing &lt;em&gt;and&lt;/em&gt; lending withdrawals&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Liquidation buffers&lt;/td&gt;
&lt;td&gt;4%–12.5%&lt;/td&gt;
&lt;td&gt;7.5%–20%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Loss waterfall&lt;/td&gt;
&lt;td&gt;Insurance → Junior → Senior&lt;/td&gt;
&lt;td&gt;Insurance → Junior → &lt;strong&gt;Protocol Treasury&lt;/strong&gt; → Senior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Tranche yield targets&lt;/td&gt;
&lt;td&gt;Senior ~9%, Junior ~32% APY&lt;/td&gt;
&lt;td&gt;Senior ~8.67%, Junior ~24–27%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Options cycle cadence&lt;/td&gt;
&lt;td&gt;weekly (Friday→Friday)&lt;/td&gt;
&lt;td&gt;"weekly or biweekly depending on the asset"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Plus a fee the docs' fee page doesn't carry at all: an &lt;strong&gt;~7% "Idle Routing Fee"&lt;/strong&gt; on yield from idle pool capital deployed to onchain money markets.&lt;/p&gt;

&lt;p&gt;Individually, each looks like a drafting slip. Collectively they describe &lt;strong&gt;two different products&lt;/strong&gt;. And #2 is the scary one: if "borrowing withdrawals" means drawing loan proceeds, a 1% fee on a 50%-LTV draw is 2% of borrowed notional — a de-facto origination fee sitting directly under the docs' "no origination fee, ever" headline.&lt;/p&gt;

&lt;p&gt;The docs' waterfall actually &lt;em&gt;undersells&lt;/em&gt; the real structure (#4 gives Senior an extra protection layer). So this isn't a company hiding costs in fine print — it's a company whose two documents drifted apart, in both directions, on the numbers its entire risk model stands on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The method (an afternoon, mostly grep)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pull both documents as text.&lt;/strong&gt; Curl the HTML, strip tags. If the legal docs live in GitBook, request &lt;code&gt;/llms.txt&lt;/code&gt; and the &lt;code&gt;.md&lt;/code&gt; version of each page — no scraping needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extract every number with its context line.&lt;/strong&gt; Percentages, basis points, time periods, fee names, waterfall orders. &lt;code&gt;grep -nE '[0-9]+(\.[0-9]+)?\s*(%|bps|basis points)' terms.md &amp;gt; terms_hits.txt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Join on concept, not string.&lt;/strong&gt; "Withdrawal fee", "withdrawals from the protocol", "funds leaving the pool" — same concept, three phrasings. This is the step that takes actual reading; budget an hour.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diff the pairs.&lt;/strong&gt; For every concept with a number on both sides, do the numbers match? Every mismatch goes in a table with section citations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check for orphans.&lt;/strong&gt; Numbers that appear in ONE document only — like that 7% idle routing fee. Those are often the most interesting finds.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. No fuzzing, no testnet exploits, no chain forensics — just patient reading of the two documents a company publishes about itself.&lt;/p&gt;

&lt;p&gt;I put the method on camera here (70 seconds, using the public Spout material): &lt;a href="https://www.youtube.com/watch?v=4pLWgMKtVRI" rel="noopener noreferrer"&gt;youtube.com/watch?v=4pLWgMKtVRI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why founders should care
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The document users would sue under and the document users read first are different products.&lt;/strong&gt; In a dispute, the ToS wins. In a purchase decision, the docs win. When they disagree, you've built a lawsuit generator with your marketing budget.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each divergence is cheap to fix &lt;em&gt;now&lt;/em&gt;.&lt;/strong&gt; It's a one-line correction — or a decision to actually align the product with one of the two claims. After launch, after a liquidation event, after a regulator asks? Expensive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's not just fintech.&lt;/strong&gt; I ran the same 5-minute check on three other crypto products' public materials last week: &lt;strong&gt;all three had gaps&lt;/strong&gt; — one had a flagship marketing claim its ToS never mentions, two had fee structures in one document and absent from the other. The pattern is the norm, not the exception.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The 5-minute self-check
&lt;/h2&gt;

&lt;p&gt;Open your own pricing/docs page and your own ToS in two windows. Search both for: every &lt;code&gt;%&lt;/code&gt;, every &lt;code&gt;fee&lt;/code&gt;, every &lt;code&gt;fee&lt;/code&gt;-adjacent noun, &lt;code&gt;APY&lt;/code&gt;, &lt;code&gt;guarantee&lt;/code&gt;, &lt;code&gt;freeze&lt;/code&gt;, &lt;code&gt;terminate&lt;/code&gt;, &lt;code&gt;refund&lt;/code&gt;. Ask of each hit: &lt;em&gt;does the other document agree with this number, or is it silent?&lt;/em&gt; Silence counts too — a fee that exists in the ToS but not the docs page is how "hidden fees" headlines get written.&lt;/p&gt;

&lt;p&gt;The fix, if you find drift: render both documents from &lt;strong&gt;one canonical numbers source&lt;/strong&gt;. Fees, buffers, waterfalls, yield targets — define each number once, in one file, and generate both outputs from it. Documentation drift is a build problem, not a writing problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  I do this as a service
&lt;/h2&gt;

&lt;p&gt;Documentation-vs-Terms review for fintech and crypto products: I cross-check your docs, ToS, whitepaper and marketing site for contradictions, gaps, and orphan claims — delivered as a cited table of findings plus fix recommendations within 72 hours. Documentation review, not legal advice (I'm not a lawyer; your counsel makes the calls — I make sure they see every mismatch in one place).&lt;/p&gt;

&lt;p&gt;Method + case studies: &lt;a href="https://loveoftheai.github.io/demo-videos/audit.html" rel="noopener noreferrer"&gt;loveoftheai.github.io/demo-videos/audit.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Spout teardown that started this (with the full six-contradiction table): &lt;a href="https://loveoftheai.github.io/spout-teardown/" rel="noopener noreferrer"&gt;loveoftheai.github.io/spout-teardown/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;All findings cited in this post are from Spout's public documents (spout.finance/docs and spout.finance/terms) as of Sep 21, 2026, and were published in the teardown before this article. Not investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>documentation</category>
      <category>fintech</category>
      <category>crypto</category>
    </item>
    <item>
      <title>I cut launch trailers for free before anyone pays me — here's why that works</title>
      <dc:creator>Justin Koo</dc:creator>
      <pubDate>Mon, 21 Sep 2026 19:37:41 +0000</pubDate>
      <link>https://dev.to/loveoftheai/i-cut-launch-trailers-for-free-before-anyone-pays-me-heres-why-that-works-3g3m</link>
      <guid>https://dev.to/loveoftheai/i-cut-launch-trailers-for-free-before-anyone-pays-me-heres-why-that-works-3g3m</guid>
      <description>&lt;p&gt;You're two weeks from launch. You need a 30-60 second trailer. You DM a few video editors and get back: &lt;strong&gt;$1,500-5,000, 2-4 weeks, 50% upfront&lt;/strong&gt;, and a portfolio of videos for &lt;em&gt;other people's&lt;/em&gt; products.&lt;/p&gt;

&lt;p&gt;You have no way to know what &lt;em&gt;your&lt;/em&gt; trailer will look like until you've already paid.&lt;/p&gt;

&lt;h2&gt;
  
  
  The spec-first workflow
&lt;/h2&gt;

&lt;p&gt;I flipped the order. Before anyone pays me anything, I cut the actual trailer for the product — from nothing but its &lt;strong&gt;public site, repo, and posts&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read everything public: landing page, docs, changelog, founder posts.&lt;/li&gt;
&lt;li&gt;Write the script: hook, product, receipts, offer. Every claim sourced from public material.&lt;/li&gt;
&lt;li&gt;Cut the real thing overnight: screen captures with motion, scripted voice-over, 1080p.&lt;/li&gt;
&lt;li&gt;Deliver it labeled as a &lt;strong&gt;spec trailer&lt;/strong&gt; — a draft cut by someone who has never talked to you.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then the founder judges the real thing, not promises. If the format fits, the paid version (repo access, real footage, revisions) follows. If it doesn't, they lost nothing and keep the video.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two real examples
&lt;/h2&gt;

&lt;p&gt;Both unsolicited, both clearly labeled as spec trailers, all facts from public sources.&lt;/p&gt;

&lt;p&gt;Poko Motion — a live AI product. 40 seconds, cut in one sitting from their public site: hook card, product sections, honest end card.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/HaxdQ0_Rbgo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;PRIMO AI — a fitness app still stuck in app review, with zero public footage. So the trailer is pure typography built from the founder's public build-in-public posts, labeled &lt;strong&gt;concept&lt;/strong&gt; because that's what it is:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Jw_L2HIsbYE" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;And a launch trailer for my own product (real captures, motion terminal, replay):&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/wq9CKdPMVPA" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "unsolicited" is a feature, not a bug
&lt;/h2&gt;

&lt;p&gt;A spec trailer proves three things a portfolio can't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt; — overnight, not a two-week pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Taste&lt;/strong&gt; — the founder sees their own product framed, not a template.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research&lt;/strong&gt; — the script only works if someone actually read the public material. If the script is wrong, you learned the vendor can't read. Cheap discovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full production recipe (PIL + ffmpeg + one neural voice, ~$0 in software) is public in &lt;a href="https://dev.to/loveoftheai/40-second-launch-trailers-with-pil-ffmpeg-and-one-neural-voice-no-editor-no-cloud-2o91"&gt;my previous post&lt;/a&gt;. The secret isn't the pipeline — it's doing the reading and the sitting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you're pre-launch and have no trailer: your public site is enough for a first cut. 30-60 seconds, first cut in 48 hours, launch-week pricing while my calendar is empty.&lt;/p&gt;

&lt;p&gt;Portfolio and contact: &lt;a href="https://loveoftheai.github.io/demo-videos/" rel="noopener noreferrer"&gt;loveoftheai.github.io/demo-videos&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Spec/concept trailers are drafts made from public material only and labeled as such inside the video. If you're Poko, PRIMO, or another company above and want yours taken down or re-cut with real access — DMs open.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>marketing</category>
      <category>indiehackers</category>
      <category>productlaunch</category>
    </item>
    <item>
      <title>40-second launch trailers with PIL, ffmpeg and one neural voice — no editor, no cloud</title>
      <dc:creator>Justin Koo</dc:creator>
      <pubDate>Mon, 21 Sep 2026 18:50:58 +0000</pubDate>
      <link>https://dev.to/loveoftheai/40-second-launch-trailers-with-pil-ffmpeg-and-one-neural-voice-no-editor-no-cloud-2o91</link>
      <guid>https://dev.to/loveoftheai/40-second-launch-trailers-with-pil-ffmpeg-and-one-neural-voice-no-editor-no-cloud-2o91</guid>
      <description>&lt;p&gt;I build 40–60 second launch trailers for small AI products, and the entire pipeline is &lt;strong&gt;Pillow, ffmpeg and one neural voice&lt;/strong&gt;. No timeline editor, no cloud video service, no stock template. This post is the actual recipe — every command is real and runs on a laptop.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/HaxdQ0_Rbgo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not an editor (or a video model)
&lt;/h2&gt;

&lt;p&gt;A 40s launch trailer is not cinematography. It's three layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Typography cards&lt;/strong&gt; — big statements, one per beat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Motion&lt;/strong&gt; — screenshots or cards that move just enough to feel alive&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice&lt;/strong&gt; — 5 sentences of script, read clean&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Video models generate &lt;em&gt;footage&lt;/em&gt;, but founders don't need footage of their product — they need their &lt;strong&gt;actual UI&lt;/strong&gt; shown with rhythm and a voice that lands. And a timeline editor is slow precisely because the format is so rigid: 5 beats, card → screen → card. Rigid formats should be code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 1 — cards with Pillow
&lt;/h2&gt;

&lt;p&gt;One card = one &lt;code&gt;ImageDraw&lt;/code&gt; pass. Palette locked to 4 colors, one font family, accent bars instead of decoration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ImageDraw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ImageFont&lt;/span&gt;

&lt;span class="n"&gt;BG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ACC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DIM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;238&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;232&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;235&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;155&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;145&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;BG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageDraw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;big&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageFont&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;truetype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;118&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;380&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MOST FITNESS APPS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;FG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;520&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RENT THEIR BRAIN.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;FG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;560&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;716&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ACC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# accent bar
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole hook card is ~15 lines. The rule that matters: &lt;strong&gt;one idea per card, one accent per card&lt;/strong&gt;. If a card needs two accent bars, it's two cards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2 — motion with ffmpeg zoompan
&lt;/h2&gt;

&lt;p&gt;Ken Burns on a static card, 4K canvas downscaled to 1080 (this is the classic zoompan aliasing fix):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-loop&lt;/span&gt; 1 &lt;span class="nt"&gt;-i&lt;/span&gt; card.png &lt;span class="nt"&gt;-vf&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"scale=3840:2160,zoompan=z='min(1+0.0009*on,1.12)':d=210:&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
   x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=1920x1080:fps=30"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; 7 &lt;span class="nt"&gt;-c&lt;/span&gt;:v libx264 &lt;span class="nt"&gt;-pix_fmt&lt;/span&gt; yuv420p card_move.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;d=210&lt;/code&gt; = 7 seconds × 30fps. The &lt;code&gt;min()&lt;/code&gt; cap is what stops the classic zoompan runaway zoom. For product screenshots the same filter gives you a slow push-in — a static screenshot suddenly reads as "demo".&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 3 — one neural voice
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;edge-tts &lt;span class="nt"&gt;--voice&lt;/span&gt; en-US-ChristopherNeural &lt;span class="nt"&gt;--rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+10% &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--text&lt;/span&gt; &lt;span class="s2"&gt;"Most fitness apps rent their intelligence from someone else's cloud."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--write-media&lt;/span&gt; seg1.mp3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deep voice, +10% pace, five segments. Script discipline: &lt;strong&gt;one sentence per segment&lt;/strong&gt;, written &lt;em&gt;after&lt;/em&gt; the cards, so the voice confirms what the eye just read instead of racing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assembly — the mux trick that keeps audio in sync
&lt;/h2&gt;

&lt;p&gt;Per segment, pad the audio to the exact video length (never rely on &lt;code&gt;-shortest&lt;/code&gt;, it clips tails):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; seg1.mp4 &lt;span class="nt"&gt;-i&lt;/span&gt; seg1.mp3 &lt;span class="nt"&gt;-filter_complex&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"[1:a]apad=whole_dur=7.0,atrim=0:7.0[a]"&lt;/span&gt; &lt;span class="nt"&gt;-map&lt;/span&gt; 0:v &lt;span class="nt"&gt;-map&lt;/span&gt; &lt;span class="s2"&gt;"[a]"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt;:v copy seg1_mux.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then concat and web-optimize:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"file 'seg1_mux.mp4'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;file 'seg2_mux.mp4'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; list.txt
ffmpeg &lt;span class="nt"&gt;-f&lt;/span&gt; concat &lt;span class="nt"&gt;-safe&lt;/span&gt; 0 &lt;span class="nt"&gt;-i&lt;/span&gt; list.txt &lt;span class="nt"&gt;-c&lt;/span&gt; copy &lt;span class="nt"&gt;-movflags&lt;/span&gt; +faststart trailer.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Total render time for a 40s trailer: &lt;strong&gt;under 3 minutes&lt;/strong&gt; on a small ARM box. The slow part is the script — always is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The spec-trailer move
&lt;/h2&gt;

&lt;p&gt;Here's the workflow that changed my conversion rate: when a founder posts "I need a launch video", I don't send a quote. I &lt;strong&gt;cut a spec trailer from their public site overnight&lt;/strong&gt; — their screenshots, their copy, my script and motion — clearly labeled "spec trailer" in the end card, facts only from public sources. They wake up to their product looking like a real launch.&lt;/p&gt;

&lt;p&gt;The video at the top of this post is one of those, cut in one sitting. A second example, this one from a real browser capture plus a terminal sequence rendered frame-by-frame with PIL:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/wq9CKdPMVPA" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Ethics guardrail that keeps this honest: the spec is labeled a spec, nothing is invented, and the founder owes nothing if the format doesn't fit. It's a sample with their name on it, not a finished deliverable held hostage.&lt;/p&gt;

&lt;h2&gt;
  
  
  When this stack is the wrong tool
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You need live-action humans → camera, always&lt;/li&gt;
&lt;li&gt;You need 3D → Blender, and honestly, hire someone&lt;/li&gt;
&lt;li&gt;The product is visual-noise (games, image models) → capture matters more than typography, and capture is manual&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For everything else — dev tools, AI apps, infra, anything with a UI and a sentence of value prop — this pipeline turns "launch video" from a two-week agency project into a 48-hour turnaround.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I do these commercially — $99 launch-week rate, 48h delivery, script + voice + motion included. Samples and pricing: &lt;a href="https://loveoftheai.github.io/demo-videos" rel="noopener noreferrer"&gt;https://loveoftheai.github.io/demo-videos&lt;/a&gt; — or find me on X &lt;a href="https://x.com/wuwei2022" rel="noopener noreferrer"&gt;@wuwei2022&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ffmpeg</category>
      <category>python</category>
      <category>sideprojects</category>
      <category>indiehackers</category>
    </item>
  </channel>
</rss>
