Skip to content

feat(autopay): Remotion video pipeline + add-card screenshot (#158913… - #171

Merged
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets
Aug 18, 2026
Merged

feat(autopay): Remotion video pipeline + add-card screenshot (#158913…#171
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets

Conversation

@junaidsarfrazdev

@junaidsarfrazdevjunaidsarfrazdev commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds the video + screenshot assets on top of the AutoPay docs merged in #169.

#158914 — Remotion video pipeline

  • Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never installed by npm ci nor walked by the site build. tsconfig excludes it; renders run manually via cd remotion && npm run render.
  • Reusable <VideoEmbed> component (poster-first, preload=none, click-to-play).
  • Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
  • 5 clips embedded into the business page (setup, self-service, add-card, retry-to-recovery, notifications), sequenced from the real product screenshots via the Reel component — not synthetic mockups.

#158913 — screenshots

  • 8 real betabulk captures (John Doe subs): cards-02-add-card, portal-01-summary-active (replaces the wrong mockup flagged in 158909 :: docs: AutoPay public documentation #169), portal-02-trialing, portal-03-canceled-pending-reactivation, portal-04-expired (new — the Expired step had no image), portal-05-no-cards, recovery-01-past-due, states-03-magic-link-invalid.
  • Asset manifest under static/img/business/autopay/MANIFEST.md, which records for every asset whether it is a real capture or one of Menna's mockups, and why.

What is still a mockup (all listed in MANIFEST.md, none blocking this PR)

  • The three cancel/reactivate modal dialogs — the subs exist and portal-03 was captured from one, but the dialogs need an interactive click on the live portal, which was not viable here (CDP Page.captureScreenshot times out; the extension viewport caps at 360px). Capture via Menna or a follow-up session; the sub URLs are ready.
  • recovery-02-payment-confirmed — needs a completed payment (card entry).
  • states-01/02/04, notifications-01..06.
  • Consequently two clips still contain some mockup frames: retry-to-recovery (recovery-02) and notification-emails (notifications-01/03/05).

Copy alignment with Ankit's clip scripts (#158914 R5) is still worth a pass before these are treated as final.


Description corrected 2026-08-18 after @claude's review. The earlier body said the 5 clips were "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914)" and that a portal-01 recapture was pending. That was written before 38bf32a, which recaptured portal-01 and rebuilt every clip from the real screenshots, so the note described a state the branch had already moved past — and the TODO markers the review correctly could not find were never added because they had stopped being true. Adding them now would label real captures as provisional.

junaidsarfrazdevand others added 4 commits August 13, 2026 19:26
…, #158914)
Adds the video + screenshot assets on top of the AutoPay docs merged in #169.
#158914 — Remotion video pipeline:
- Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never
installed by npm ci nor walked by the site build. tsconfig excludes it; renders
run manually via `cd remotion && npm run render`.
- Reusable <VideoEmbed> component (poster-first, preload=none, reduced-motion safe).
- Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
- 5 first-cut clips embedded into the business page (setup, self-service, add-card,
retry-to-recovery, notifications).
#158913 — screenshots:
- cards-02-add-card.png captured from betabulk (John Doe), fills the add-card gap.
- Asset manifest under static/img/business/autopay/MANIFEST.md.
NOTE: the 5 clips are FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each
composition, the business page, and remotion/README.md. They must be revisited and
re-recorded once the betabulk AutoPay scenario URLs are available, with copy aligned
to Ankit's clip scripts (#158914 R5). portal-01 recapture (flagged in #169) also pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#158913, #158914)
Replaces mockups with real customer-portal captures (John Doe / betabulk) and
rebuilds the Remotion clips to sequence those real screenshots.
Screenshots (#158913) — 7 real betabulk captures now in the business-page sliders:
portal-01-summary-active (replaces the flagged wrong mockup), portal-02-trialing,
portal-03-canceled-pending-reactivation, portal-04-expired (new + wired into the
previously image-less Expired step), portal-05-no-cards, recovery-01-past-due,
states-03-magic-link-invalid. Kept as mockups (see MANIFEST.md): the three
cancel/reactivate dialogs, recovery-02, states-01/02/04, notifications-01..06.
Videos (#158914) — rebuilt from the real screenshots: new Reel component sequences
the real PNGs (staticFile from remotion/public/screens, copied by render-all.mjs,
gitignored) with captions + crossfades; all 5 clips re-rendered.
typecheck + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@junaidsarfrazdev
junaidsarfrazdev marked this pull request as ready for review August 18, 2026 13:51
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 44s —— View job


Claude finished the review

Todo list:

  • Gather context (PR diff, changed files, CLAUDE.md)
  • Review remotion/ workspace isolation (package.json, tsconfig, gitignore)
  • Review VideoEmbed component
  • Review AutoPay docs page changes
  • Review asset manifest / screenshots
  • Post final review

Summary

Solid, well-scoped PR. The remotion/ isolation is done carefully (own package.json/tsconfig/lockfile, remotion/node_modules|out|public gitignored, root tsconfig.json excludes it, README.md explicitly documents why npm ci/typecheck/build never touch it). VideoEmbed is a clean poster-first, click-to-play component (preload="none", respects prefers-reduced-motion, dark-mode aware CSS). The five compositions accurately match what's described in static/img/business/autopay/MANIFEST.md, and all referenced image/video paths in docs/business/autopay/index.md resolve to real committed files.

Finding

PR description says the placeholder flags are missing from the diff. The PR body states the 5 clips are "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each composition, the business page, and remotion/README.md." I grepped the full diff (compositions, Root.tsx, docs/business/autopay/index.md, remotion/README.md) for TODO(#158914), placeholder, and first-cut — none of these markers actually exist anywhere in the changed files. Right now a reader of docs/business/autopay/index.md or remotion/src/compositions/*.tsx has no signal that these 5 videos are provisional and pending re-recording against real betabulk scenario URLs + Ankit's clip scripts. Since this page ships to real merchants, worth either adding the flags as described or updating the PR description to match reality.

Fix this →

Minor / non-blocking

  • src/components/VideoEmbed/index.tsx:44-54 — when prefers-reduced-motion is set, clicking the poster swaps in the <video> with autoPlay={false}, so the user has to click twice (once on the custom poster button, once on the native play control) to actually start playback. Reasonable accessibility-first tradeoff, just noting the double-click UX.
  • Couldn't run npm run typecheck / npm run build myself — Bash execution required interactive approval in this environment that wasn't granted. Given the isolation approach is thoroughly documented and cross-checked in remotion/README.md (including "verified: a deliberate type error inside remotion/ does not fail the root typecheck"), I'd suggest CI confirm this rather than re-deriving it manually.
    · branch: task/158913-158914-autopay-assets

`autoPlay={!reduced}` meant a reader with `prefers-reduced-motion` clicked the
poster, got a paused `<video>`, and had to click the native control to actually
start it. That gate misreads the preference: it governs UNSOLICITED motion, and
`playing` only becomes true from the poster click, so playback here is always
user-initiated.
Autoplay is unconditional now, which makes `usePrefersReducedMotion` dead — the
hook existed for that one prop, so it goes with it.
Raised as a non-blocking note by @claude on PR #171.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Thanks — the finding was correct, but the fix is the other branch of what you offered.

The TODO(#158914) markers are genuinely absent, and should stay absent. They were never added because they stopped being true: 38bf32a (17 Aug) recaptured portal-01 and rebuilt all 5 clips from the real betabulk screenshots via the new Reel component. The PR body still carried the pre-rebuild note, so it described a state the branch had already moved past. Adding "first-cut placeholder" flags now would label real captures as provisional — the opposite of accurate.

The branch already documents this, which is worth checking against next time the two disagree:

  • static/img/business/autopay/MANIFEST.md § "Videos (#158914) — rebuilt from the REAL screenshots"
  • remotion/README.md, first line: "Clips are built from the REAL product screenshots."

So I've corrected the PR description instead, and it now also records what genuinely is still a mockup — the three cancel/reactivate modal dialogs (need an interactive click on the live portal), recovery-02, states-01/02/04, notifications-01..06 — and therefore that two clips still contain some mockup frames. That was the real gap: the honest caveat existed in MANIFEST.md but not in the PR.

Minor finding — fixed in 152610a. You were right that reduced-motion caused a double click. The gate also misread the preference: prefers-reduced-motion governs unsolicited motion, and playing only becomes true from the poster click, so playback there is always user-initiated. autoPlay is unconditional now, and usePrefersReducedMotion went with it since it existed for that one prop. npm run typecheck green.

On the third point — CI is the right place to confirm the remotion/ isolation, agreed. npm run typecheck passes locally after this change.

@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 28s —— View job


Claude finished re-reviewing @junaidsarfrazdev's PR

Todo list:

  • Gather context (PR diff, prior review discussion, CLAUDE.md)
  • Verify the 152610a fix (double-click / prefers-reduced-motion change) in VideoEmbed
  • Verify the PR description correction matches MANIFEST.md / README.md
  • Re-check remaining files (compositions, docs page, manifest) for anything new
  • Post final review

Summary

Both follow-ups from the previous review are handled correctly:

  • PR description: now accurately reflects that all 5 clips are rebuilt from real betabulk screenshots (not first-cut placeholders), and lists the genuine remaining mockups (3 modal dialogs, recovery-02, states-01/02/04, notifications-01..06). This matches static/img/business/autopay/MANIFEST.md and remotion/README.md, and docs/business/autopay/index.md's in-page comment was updated to match (git diff 9ca313e..HEAD -- docs/business/autopay/index.md) — the stale TODO(#158914) "FIRST-CUT PLACEHOLDERS" comment is gone, replaced with an accurate "built from the real betabulk screenshots" note.
  • 152610a: the fix itself is correct — playing only flips true from the poster's own click handler (src/components/VideoEmbed/index.tsx:51), so gating autoPlay on prefers-reduced-motion was never actually suppressing unsolicited motion, just adding a redundant second click. Making autoPlay unconditional and dropping the now-dead usePrefersReducedMotion hook is the right call, and the inline comment explains the non-obvious "why."

Finding

src/components/VideoEmbed/README.md:36-37 documents the behavior 152610a just removed. It still reads:

Reduced motion. When the OS requests reduced motion, the video does not autoplay after the click (autoPlay={!reduced}); the reader controls playback.

autoPlay={!reduced} and the reduced state no longer exist in index.tsxautoPlay is now unconditional. A future reader of this component's own README would be told about behavior that isn't there anymore, and would be citing dead code ({!reduced}) if they went looking for it.

Fix this →

Minor / non-blocking

  • docs/superpowers/plans/2026-08-12-autopay-assets-docs.md and docs/superpowers/specs/2026-08-12-autopay-assets-docs-design.md also mention usePrefersReducedMotion, but these are dated planning artifacts (design history), not live component docs — I wouldn't touch them.
  • Same limitation as the last review: couldn't run npm run typecheck myself (Bash execution needs interactive approval that wasn't granted here). You noted it's green locally after 152610a; I'd still lean on CI to confirm.

Everything else — the remotion/ isolation, the manifest's real-vs-mockup accounting, and the docs page's image/video paths — is unchanged since the last pass and still checks out.
· branch: task/158913-158914-autopay-assets

…emoved
It still documented `autoPlay={!reduced}` and a `reduced` state, neither of
which exists — so the component's own README sent a reader looking for deleted
code. Replaced with what the code does now, and why it is not a reduced-motion
violation: the `<video>` only mounts from the poster's click handler, so
playback is always user-initiated.
Caught by @claude on PR #171. I had grepped `index.tsx` for the hook when
removing it, but not the component's README beside it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Good catch — fixed in 70d02d0.

src/components/VideoEmbed/README.md still documented autoPlay={!reduced} and a reduced state, so the component's own README was pointing a reader at code deleted in 152610a. It now describes what the code does and why it isn't a reduced-motion violation: the <video> only mounts from the poster's click handler, so playback is always user-initiated.

My miss — when removing the hook I grepped index.tsx for it but not the README sitting beside it. I've swept the rest: no live reference to usePrefersReducedMotion or {!reduced} remains outside the dated planning artifacts.

Agreed on both minor points. The docs/superpowers/plans|specs files are design history from 2026-08-12 and should keep saying what was decided then — rewriting them would falsify the record. And npm run typecheck is green locally after both commits; CI is the right place to confirm that and the remotion/ isolation.

One thing worth recording since it isn't visible from the diff: I could not verify playback end-to-end in a browser. The clips don't decode in the Chrome available here — opening setup-subscription.mp4 directly, with no React involved, hangs at readyState 0 / videoWidth 0 with no error, though canPlayType('video/mp4; codecs="avc1.42E01E") reports probably. The files themselves are fine — valid faststart MP4 (moov before mdat), served 200 video/mp4, 540 KB — so this reads as a Linux Chromium build whose canPlayType over-reports while the proprietary H.264 decoder is absent, not a defect in the assets or the component. Someone should click through the five embeds on a normal browser before merge; the component behaviour either side of that is verified (poster-first, no <video> in the DOM until the click, then mounted with autoplay + muted and no second click needed).

@junaidsarfrazdev
junaidsarfrazdev merged commit 2aa9a7d into devAug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@junaidsarfrazdev
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat(autopay): Remotion video pipeline + add-card screenshot (#158913… by junaidsarfrazdev · Pull Request #171 · ottuco/docs · GitHub
Skip to content

feat(autopay): Remotion video pipeline + add-card screenshot (#158913… - #171

Merged
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets
Aug 18, 2026
Merged

feat(autopay): Remotion video pipeline + add-card screenshot (#158913…#171
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets

Conversation

@junaidsarfrazdev

@junaidsarfrazdevjunaidsarfrazdev commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds the video + screenshot assets on top of the AutoPay docs merged in #169.

#158914 — Remotion video pipeline

  • Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never installed by npm ci nor walked by the site build. tsconfig excludes it; renders run manually via cd remotion && npm run render.
  • Reusable <VideoEmbed> component (poster-first, preload=none, click-to-play).
  • Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
  • 5 clips embedded into the business page (setup, self-service, add-card, retry-to-recovery, notifications), sequenced from the real product screenshots via the Reel component — not synthetic mockups.

#158913 — screenshots

  • 8 real betabulk captures (John Doe subs): cards-02-add-card, portal-01-summary-active (replaces the wrong mockup flagged in 158909 :: docs: AutoPay public documentation #169), portal-02-trialing, portal-03-canceled-pending-reactivation, portal-04-expired (new — the Expired step had no image), portal-05-no-cards, recovery-01-past-due, states-03-magic-link-invalid.
  • Asset manifest under static/img/business/autopay/MANIFEST.md, which records for every asset whether it is a real capture or one of Menna's mockups, and why.

What is still a mockup (all listed in MANIFEST.md, none blocking this PR)

  • The three cancel/reactivate modal dialogs — the subs exist and portal-03 was captured from one, but the dialogs need an interactive click on the live portal, which was not viable here (CDP Page.captureScreenshot times out; the extension viewport caps at 360px). Capture via Menna or a follow-up session; the sub URLs are ready.
  • recovery-02-payment-confirmed — needs a completed payment (card entry).
  • states-01/02/04, notifications-01..06.
  • Consequently two clips still contain some mockup frames: retry-to-recovery (recovery-02) and notification-emails (notifications-01/03/05).

Copy alignment with Ankit's clip scripts (#158914 R5) is still worth a pass before these are treated as final.


Description corrected 2026-08-18 after @claude's review. The earlier body said the 5 clips were "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914)" and that a portal-01 recapture was pending. That was written before 38bf32a, which recaptured portal-01 and rebuilt every clip from the real screenshots, so the note described a state the branch had already moved past — and the TODO markers the review correctly could not find were never added because they had stopped being true. Adding them now would label real captures as provisional.

junaidsarfrazdevand others added 4 commits August 13, 2026 19:26
…, #158914)
Adds the video + screenshot assets on top of the AutoPay docs merged in #169.
#158914 — Remotion video pipeline:
- Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never
installed by npm ci nor walked by the site build. tsconfig excludes it; renders
run manually via `cd remotion && npm run render`.
- Reusable <VideoEmbed> component (poster-first, preload=none, reduced-motion safe).
- Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
- 5 first-cut clips embedded into the business page (setup, self-service, add-card,
retry-to-recovery, notifications).
#158913 — screenshots:
- cards-02-add-card.png captured from betabulk (John Doe), fills the add-card gap.
- Asset manifest under static/img/business/autopay/MANIFEST.md.
NOTE: the 5 clips are FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each
composition, the business page, and remotion/README.md. They must be revisited and
re-recorded once the betabulk AutoPay scenario URLs are available, with copy aligned
to Ankit's clip scripts (#158914 R5). portal-01 recapture (flagged in #169) also pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#158913, #158914)
Replaces mockups with real customer-portal captures (John Doe / betabulk) and
rebuilds the Remotion clips to sequence those real screenshots.
Screenshots (#158913) — 7 real betabulk captures now in the business-page sliders:
portal-01-summary-active (replaces the flagged wrong mockup), portal-02-trialing,
portal-03-canceled-pending-reactivation, portal-04-expired (new + wired into the
previously image-less Expired step), portal-05-no-cards, recovery-01-past-due,
states-03-magic-link-invalid. Kept as mockups (see MANIFEST.md): the three
cancel/reactivate dialogs, recovery-02, states-01/02/04, notifications-01..06.
Videos (#158914) — rebuilt from the real screenshots: new Reel component sequences
the real PNGs (staticFile from remotion/public/screens, copied by render-all.mjs,
gitignored) with captions + crossfades; all 5 clips re-rendered.
typecheck + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@junaidsarfrazdev
junaidsarfrazdev marked this pull request as ready for review August 18, 2026 13:51
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 44s —— View job


Claude finished the review

Todo list:

  • Gather context (PR diff, changed files, CLAUDE.md)
  • Review remotion/ workspace isolation (package.json, tsconfig, gitignore)
  • Review VideoEmbed component
  • Review AutoPay docs page changes
  • Review asset manifest / screenshots
  • Post final review

Summary

Solid, well-scoped PR. The remotion/ isolation is done carefully (own package.json/tsconfig/lockfile, remotion/node_modules|out|public gitignored, root tsconfig.json excludes it, README.md explicitly documents why npm ci/typecheck/build never touch it). VideoEmbed is a clean poster-first, click-to-play component (preload="none", respects prefers-reduced-motion, dark-mode aware CSS). The five compositions accurately match what's described in static/img/business/autopay/MANIFEST.md, and all referenced image/video paths in docs/business/autopay/index.md resolve to real committed files.

Finding

PR description says the placeholder flags are missing from the diff. The PR body states the 5 clips are "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each composition, the business page, and remotion/README.md." I grepped the full diff (compositions, Root.tsx, docs/business/autopay/index.md, remotion/README.md) for TODO(#158914), placeholder, and first-cut — none of these markers actually exist anywhere in the changed files. Right now a reader of docs/business/autopay/index.md or remotion/src/compositions/*.tsx has no signal that these 5 videos are provisional and pending re-recording against real betabulk scenario URLs + Ankit's clip scripts. Since this page ships to real merchants, worth either adding the flags as described or updating the PR description to match reality.

Fix this →

Minor / non-blocking

  • src/components/VideoEmbed/index.tsx:44-54 — when prefers-reduced-motion is set, clicking the poster swaps in the <video> with autoPlay={false}, so the user has to click twice (once on the custom poster button, once on the native play control) to actually start playback. Reasonable accessibility-first tradeoff, just noting the double-click UX.
  • Couldn't run npm run typecheck / npm run build myself — Bash execution required interactive approval in this environment that wasn't granted. Given the isolation approach is thoroughly documented and cross-checked in remotion/README.md (including "verified: a deliberate type error inside remotion/ does not fail the root typecheck"), I'd suggest CI confirm this rather than re-deriving it manually.
    · branch: task/158913-158914-autopay-assets

`autoPlay={!reduced}` meant a reader with `prefers-reduced-motion` clicked the
poster, got a paused `<video>`, and had to click the native control to actually
start it. That gate misreads the preference: it governs UNSOLICITED motion, and
`playing` only becomes true from the poster click, so playback here is always
user-initiated.
Autoplay is unconditional now, which makes `usePrefersReducedMotion` dead — the
hook existed for that one prop, so it goes with it.
Raised as a non-blocking note by @claude on PR #171.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Thanks — the finding was correct, but the fix is the other branch of what you offered.

The TODO(#158914) markers are genuinely absent, and should stay absent. They were never added because they stopped being true: 38bf32a (17 Aug) recaptured portal-01 and rebuilt all 5 clips from the real betabulk screenshots via the new Reel component. The PR body still carried the pre-rebuild note, so it described a state the branch had already moved past. Adding "first-cut placeholder" flags now would label real captures as provisional — the opposite of accurate.

The branch already documents this, which is worth checking against next time the two disagree:

  • static/img/business/autopay/MANIFEST.md § "Videos (#158914) — rebuilt from the REAL screenshots"
  • remotion/README.md, first line: "Clips are built from the REAL product screenshots."

So I've corrected the PR description instead, and it now also records what genuinely is still a mockup — the three cancel/reactivate modal dialogs (need an interactive click on the live portal), recovery-02, states-01/02/04, notifications-01..06 — and therefore that two clips still contain some mockup frames. That was the real gap: the honest caveat existed in MANIFEST.md but not in the PR.

Minor finding — fixed in 152610a. You were right that reduced-motion caused a double click. The gate also misread the preference: prefers-reduced-motion governs unsolicited motion, and playing only becomes true from the poster click, so playback there is always user-initiated. autoPlay is unconditional now, and usePrefersReducedMotion went with it since it existed for that one prop. npm run typecheck green.

On the third point — CI is the right place to confirm the remotion/ isolation, agreed. npm run typecheck passes locally after this change.

@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 28s —— View job


Claude finished re-reviewing @junaidsarfrazdev's PR

Todo list:

  • Gather context (PR diff, prior review discussion, CLAUDE.md)
  • Verify the 152610a fix (double-click / prefers-reduced-motion change) in VideoEmbed
  • Verify the PR description correction matches MANIFEST.md / README.md
  • Re-check remaining files (compositions, docs page, manifest) for anything new
  • Post final review

Summary

Both follow-ups from the previous review are handled correctly:

  • PR description: now accurately reflects that all 5 clips are rebuilt from real betabulk screenshots (not first-cut placeholders), and lists the genuine remaining mockups (3 modal dialogs, recovery-02, states-01/02/04, notifications-01..06). This matches static/img/business/autopay/MANIFEST.md and remotion/README.md, and docs/business/autopay/index.md's in-page comment was updated to match (git diff 9ca313e..HEAD -- docs/business/autopay/index.md) — the stale TODO(#158914) "FIRST-CUT PLACEHOLDERS" comment is gone, replaced with an accurate "built from the real betabulk screenshots" note.
  • 152610a: the fix itself is correct — playing only flips true from the poster's own click handler (src/components/VideoEmbed/index.tsx:51), so gating autoPlay on prefers-reduced-motion was never actually suppressing unsolicited motion, just adding a redundant second click. Making autoPlay unconditional and dropping the now-dead usePrefersReducedMotion hook is the right call, and the inline comment explains the non-obvious "why."

Finding

src/components/VideoEmbed/README.md:36-37 documents the behavior 152610a just removed. It still reads:

Reduced motion. When the OS requests reduced motion, the video does not autoplay after the click (autoPlay={!reduced}); the reader controls playback.

autoPlay={!reduced} and the reduced state no longer exist in index.tsxautoPlay is now unconditional. A future reader of this component's own README would be told about behavior that isn't there anymore, and would be citing dead code ({!reduced}) if they went looking for it.

Fix this →

Minor / non-blocking

  • docs/superpowers/plans/2026-08-12-autopay-assets-docs.md and docs/superpowers/specs/2026-08-12-autopay-assets-docs-design.md also mention usePrefersReducedMotion, but these are dated planning artifacts (design history), not live component docs — I wouldn't touch them.
  • Same limitation as the last review: couldn't run npm run typecheck myself (Bash execution needs interactive approval that wasn't granted here). You noted it's green locally after 152610a; I'd still lean on CI to confirm.

Everything else — the remotion/ isolation, the manifest's real-vs-mockup accounting, and the docs page's image/video paths — is unchanged since the last pass and still checks out.
· branch: task/158913-158914-autopay-assets

…emoved
It still documented `autoPlay={!reduced}` and a `reduced` state, neither of
which exists — so the component's own README sent a reader looking for deleted
code. Replaced with what the code does now, and why it is not a reduced-motion
violation: the `<video>` only mounts from the poster's click handler, so
playback is always user-initiated.
Caught by @claude on PR #171. I had grepped `index.tsx` for the hook when
removing it, but not the component's README beside it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Good catch — fixed in 70d02d0.

src/components/VideoEmbed/README.md still documented autoPlay={!reduced} and a reduced state, so the component's own README was pointing a reader at code deleted in 152610a. It now describes what the code does and why it isn't a reduced-motion violation: the <video> only mounts from the poster's click handler, so playback is always user-initiated.

My miss — when removing the hook I grepped index.tsx for it but not the README sitting beside it. I've swept the rest: no live reference to usePrefersReducedMotion or {!reduced} remains outside the dated planning artifacts.

Agreed on both minor points. The docs/superpowers/plans|specs files are design history from 2026-08-12 and should keep saying what was decided then — rewriting them would falsify the record. And npm run typecheck is green locally after both commits; CI is the right place to confirm that and the remotion/ isolation.

One thing worth recording since it isn't visible from the diff: I could not verify playback end-to-end in a browser. The clips don't decode in the Chrome available here — opening setup-subscription.mp4 directly, with no React involved, hangs at readyState 0 / videoWidth 0 with no error, though canPlayType('video/mp4; codecs="avc1.42E01E") reports probably. The files themselves are fine — valid faststart MP4 (moov before mdat), served 200 video/mp4, 540 KB — so this reads as a Linux Chromium build whose canPlayType over-reports while the proprietary H.264 decoder is absent, not a defect in the assets or the component. Someone should click through the five embeds on a normal browser before merge; the component behaviour either side of that is verified (poster-first, no <video> in the DOM until the click, then mounted with autoplay + muted and no second click needed).

@junaidsarfrazdev
junaidsarfrazdev merged commit 2aa9a7d into devAug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@junaidsarfrazdev
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(autopay): Remotion video pipeline + add-card screenshot (#158913… by junaidsarfrazdev · Pull Request #171 · ottuco/docs · GitHub
Skip to content

feat(autopay): Remotion video pipeline + add-card screenshot (#158913… - #171

Merged
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets
Aug 18, 2026
Merged

feat(autopay): Remotion video pipeline + add-card screenshot (#158913…#171
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets

Conversation

@junaidsarfrazdev

@junaidsarfrazdevjunaidsarfrazdev commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds the video + screenshot assets on top of the AutoPay docs merged in #169.

#158914 — Remotion video pipeline

  • Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never installed by npm ci nor walked by the site build. tsconfig excludes it; renders run manually via cd remotion && npm run render.
  • Reusable <VideoEmbed> component (poster-first, preload=none, click-to-play).
  • Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
  • 5 clips embedded into the business page (setup, self-service, add-card, retry-to-recovery, notifications), sequenced from the real product screenshots via the Reel component — not synthetic mockups.

#158913 — screenshots

  • 8 real betabulk captures (John Doe subs): cards-02-add-card, portal-01-summary-active (replaces the wrong mockup flagged in 158909 :: docs: AutoPay public documentation #169), portal-02-trialing, portal-03-canceled-pending-reactivation, portal-04-expired (new — the Expired step had no image), portal-05-no-cards, recovery-01-past-due, states-03-magic-link-invalid.
  • Asset manifest under static/img/business/autopay/MANIFEST.md, which records for every asset whether it is a real capture or one of Menna's mockups, and why.

What is still a mockup (all listed in MANIFEST.md, none blocking this PR)

  • The three cancel/reactivate modal dialogs — the subs exist and portal-03 was captured from one, but the dialogs need an interactive click on the live portal, which was not viable here (CDP Page.captureScreenshot times out; the extension viewport caps at 360px). Capture via Menna or a follow-up session; the sub URLs are ready.
  • recovery-02-payment-confirmed — needs a completed payment (card entry).
  • states-01/02/04, notifications-01..06.
  • Consequently two clips still contain some mockup frames: retry-to-recovery (recovery-02) and notification-emails (notifications-01/03/05).

Copy alignment with Ankit's clip scripts (#158914 R5) is still worth a pass before these are treated as final.


Description corrected 2026-08-18 after @claude's review. The earlier body said the 5 clips were "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914)" and that a portal-01 recapture was pending. That was written before 38bf32a, which recaptured portal-01 and rebuilt every clip from the real screenshots, so the note described a state the branch had already moved past — and the TODO markers the review correctly could not find were never added because they had stopped being true. Adding them now would label real captures as provisional.

junaidsarfrazdevand others added 4 commits August 13, 2026 19:26
…, #158914)
Adds the video + screenshot assets on top of the AutoPay docs merged in #169.
#158914 — Remotion video pipeline:
- Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never
installed by npm ci nor walked by the site build. tsconfig excludes it; renders
run manually via `cd remotion && npm run render`.
- Reusable <VideoEmbed> component (poster-first, preload=none, reduced-motion safe).
- Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
- 5 first-cut clips embedded into the business page (setup, self-service, add-card,
retry-to-recovery, notifications).
#158913 — screenshots:
- cards-02-add-card.png captured from betabulk (John Doe), fills the add-card gap.
- Asset manifest under static/img/business/autopay/MANIFEST.md.
NOTE: the 5 clips are FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each
composition, the business page, and remotion/README.md. They must be revisited and
re-recorded once the betabulk AutoPay scenario URLs are available, with copy aligned
to Ankit's clip scripts (#158914 R5). portal-01 recapture (flagged in #169) also pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#158913, #158914)
Replaces mockups with real customer-portal captures (John Doe / betabulk) and
rebuilds the Remotion clips to sequence those real screenshots.
Screenshots (#158913) — 7 real betabulk captures now in the business-page sliders:
portal-01-summary-active (replaces the flagged wrong mockup), portal-02-trialing,
portal-03-canceled-pending-reactivation, portal-04-expired (new + wired into the
previously image-less Expired step), portal-05-no-cards, recovery-01-past-due,
states-03-magic-link-invalid. Kept as mockups (see MANIFEST.md): the three
cancel/reactivate dialogs, recovery-02, states-01/02/04, notifications-01..06.
Videos (#158914) — rebuilt from the real screenshots: new Reel component sequences
the real PNGs (staticFile from remotion/public/screens, copied by render-all.mjs,
gitignored) with captions + crossfades; all 5 clips re-rendered.
typecheck + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@junaidsarfrazdev
junaidsarfrazdev marked this pull request as ready for review August 18, 2026 13:51
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 44s —— View job


Claude finished the review

Todo list:

  • Gather context (PR diff, changed files, CLAUDE.md)
  • Review remotion/ workspace isolation (package.json, tsconfig, gitignore)
  • Review VideoEmbed component
  • Review AutoPay docs page changes
  • Review asset manifest / screenshots
  • Post final review

Summary

Solid, well-scoped PR. The remotion/ isolation is done carefully (own package.json/tsconfig/lockfile, remotion/node_modules|out|public gitignored, root tsconfig.json excludes it, README.md explicitly documents why npm ci/typecheck/build never touch it). VideoEmbed is a clean poster-first, click-to-play component (preload="none", respects prefers-reduced-motion, dark-mode aware CSS). The five compositions accurately match what's described in static/img/business/autopay/MANIFEST.md, and all referenced image/video paths in docs/business/autopay/index.md resolve to real committed files.

Finding

PR description says the placeholder flags are missing from the diff. The PR body states the 5 clips are "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each composition, the business page, and remotion/README.md." I grepped the full diff (compositions, Root.tsx, docs/business/autopay/index.md, remotion/README.md) for TODO(#158914), placeholder, and first-cut — none of these markers actually exist anywhere in the changed files. Right now a reader of docs/business/autopay/index.md or remotion/src/compositions/*.tsx has no signal that these 5 videos are provisional and pending re-recording against real betabulk scenario URLs + Ankit's clip scripts. Since this page ships to real merchants, worth either adding the flags as described or updating the PR description to match reality.

Fix this →

Minor / non-blocking

  • src/components/VideoEmbed/index.tsx:44-54 — when prefers-reduced-motion is set, clicking the poster swaps in the <video> with autoPlay={false}, so the user has to click twice (once on the custom poster button, once on the native play control) to actually start playback. Reasonable accessibility-first tradeoff, just noting the double-click UX.
  • Couldn't run npm run typecheck / npm run build myself — Bash execution required interactive approval in this environment that wasn't granted. Given the isolation approach is thoroughly documented and cross-checked in remotion/README.md (including "verified: a deliberate type error inside remotion/ does not fail the root typecheck"), I'd suggest CI confirm this rather than re-deriving it manually.
    · branch: task/158913-158914-autopay-assets

`autoPlay={!reduced}` meant a reader with `prefers-reduced-motion` clicked the
poster, got a paused `<video>`, and had to click the native control to actually
start it. That gate misreads the preference: it governs UNSOLICITED motion, and
`playing` only becomes true from the poster click, so playback here is always
user-initiated.
Autoplay is unconditional now, which makes `usePrefersReducedMotion` dead — the
hook existed for that one prop, so it goes with it.
Raised as a non-blocking note by @claude on PR #171.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Thanks — the finding was correct, but the fix is the other branch of what you offered.

The TODO(#158914) markers are genuinely absent, and should stay absent. They were never added because they stopped being true: 38bf32a (17 Aug) recaptured portal-01 and rebuilt all 5 clips from the real betabulk screenshots via the new Reel component. The PR body still carried the pre-rebuild note, so it described a state the branch had already moved past. Adding "first-cut placeholder" flags now would label real captures as provisional — the opposite of accurate.

The branch already documents this, which is worth checking against next time the two disagree:

  • static/img/business/autopay/MANIFEST.md § "Videos (#158914) — rebuilt from the REAL screenshots"
  • remotion/README.md, first line: "Clips are built from the REAL product screenshots."

So I've corrected the PR description instead, and it now also records what genuinely is still a mockup — the three cancel/reactivate modal dialogs (need an interactive click on the live portal), recovery-02, states-01/02/04, notifications-01..06 — and therefore that two clips still contain some mockup frames. That was the real gap: the honest caveat existed in MANIFEST.md but not in the PR.

Minor finding — fixed in 152610a. You were right that reduced-motion caused a double click. The gate also misread the preference: prefers-reduced-motion governs unsolicited motion, and playing only becomes true from the poster click, so playback there is always user-initiated. autoPlay is unconditional now, and usePrefersReducedMotion went with it since it existed for that one prop. npm run typecheck green.

On the third point — CI is the right place to confirm the remotion/ isolation, agreed. npm run typecheck passes locally after this change.

@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 28s —— View job


Claude finished re-reviewing @junaidsarfrazdev's PR

Todo list:

  • Gather context (PR diff, prior review discussion, CLAUDE.md)
  • Verify the 152610a fix (double-click / prefers-reduced-motion change) in VideoEmbed
  • Verify the PR description correction matches MANIFEST.md / README.md
  • Re-check remaining files (compositions, docs page, manifest) for anything new
  • Post final review

Summary

Both follow-ups from the previous review are handled correctly:

  • PR description: now accurately reflects that all 5 clips are rebuilt from real betabulk screenshots (not first-cut placeholders), and lists the genuine remaining mockups (3 modal dialogs, recovery-02, states-01/02/04, notifications-01..06). This matches static/img/business/autopay/MANIFEST.md and remotion/README.md, and docs/business/autopay/index.md's in-page comment was updated to match (git diff 9ca313e..HEAD -- docs/business/autopay/index.md) — the stale TODO(#158914) "FIRST-CUT PLACEHOLDERS" comment is gone, replaced with an accurate "built from the real betabulk screenshots" note.
  • 152610a: the fix itself is correct — playing only flips true from the poster's own click handler (src/components/VideoEmbed/index.tsx:51), so gating autoPlay on prefers-reduced-motion was never actually suppressing unsolicited motion, just adding a redundant second click. Making autoPlay unconditional and dropping the now-dead usePrefersReducedMotion hook is the right call, and the inline comment explains the non-obvious "why."

Finding

src/components/VideoEmbed/README.md:36-37 documents the behavior 152610a just removed. It still reads:

Reduced motion. When the OS requests reduced motion, the video does not autoplay after the click (autoPlay={!reduced}); the reader controls playback.

autoPlay={!reduced} and the reduced state no longer exist in index.tsxautoPlay is now unconditional. A future reader of this component's own README would be told about behavior that isn't there anymore, and would be citing dead code ({!reduced}) if they went looking for it.

Fix this →

Minor / non-blocking

  • docs/superpowers/plans/2026-08-12-autopay-assets-docs.md and docs/superpowers/specs/2026-08-12-autopay-assets-docs-design.md also mention usePrefersReducedMotion, but these are dated planning artifacts (design history), not live component docs — I wouldn't touch them.
  • Same limitation as the last review: couldn't run npm run typecheck myself (Bash execution needs interactive approval that wasn't granted here). You noted it's green locally after 152610a; I'd still lean on CI to confirm.

Everything else — the remotion/ isolation, the manifest's real-vs-mockup accounting, and the docs page's image/video paths — is unchanged since the last pass and still checks out.
· branch: task/158913-158914-autopay-assets

…emoved
It still documented `autoPlay={!reduced}` and a `reduced` state, neither of
which exists — so the component's own README sent a reader looking for deleted
code. Replaced with what the code does now, and why it is not a reduced-motion
violation: the `<video>` only mounts from the poster's click handler, so
playback is always user-initiated.
Caught by @claude on PR #171. I had grepped `index.tsx` for the hook when
removing it, but not the component's README beside it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Good catch — fixed in 70d02d0.

src/components/VideoEmbed/README.md still documented autoPlay={!reduced} and a reduced state, so the component's own README was pointing a reader at code deleted in 152610a. It now describes what the code does and why it isn't a reduced-motion violation: the <video> only mounts from the poster's click handler, so playback is always user-initiated.

My miss — when removing the hook I grepped index.tsx for it but not the README sitting beside it. I've swept the rest: no live reference to usePrefersReducedMotion or {!reduced} remains outside the dated planning artifacts.

Agreed on both minor points. The docs/superpowers/plans|specs files are design history from 2026-08-12 and should keep saying what was decided then — rewriting them would falsify the record. And npm run typecheck is green locally after both commits; CI is the right place to confirm that and the remotion/ isolation.

One thing worth recording since it isn't visible from the diff: I could not verify playback end-to-end in a browser. The clips don't decode in the Chrome available here — opening setup-subscription.mp4 directly, with no React involved, hangs at readyState 0 / videoWidth 0 with no error, though canPlayType('video/mp4; codecs="avc1.42E01E") reports probably. The files themselves are fine — valid faststart MP4 (moov before mdat), served 200 video/mp4, 540 KB — so this reads as a Linux Chromium build whose canPlayType over-reports while the proprietary H.264 decoder is absent, not a defect in the assets or the component. Someone should click through the five embeds on a normal browser before merge; the component behaviour either side of that is verified (poster-first, no <video> in the DOM until the click, then mounted with autoplay + muted and no second click needed).

@junaidsarfrazdev
junaidsarfrazdev merged commit 2aa9a7d into devAug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@junaidsarfrazdev
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(autopay): Remotion video pipeline + add-card screenshot (#158913… by junaidsarfrazdev · Pull Request #171 · ottuco/docs · GitHub
Skip to content

feat(autopay): Remotion video pipeline + add-card screenshot (#158913… - #171

Merged
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets
Aug 18, 2026
Merged

feat(autopay): Remotion video pipeline + add-card screenshot (#158913…#171
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets

Conversation

@junaidsarfrazdev

@junaidsarfrazdevjunaidsarfrazdev commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds the video + screenshot assets on top of the AutoPay docs merged in #169.

#158914 — Remotion video pipeline

  • Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never installed by npm ci nor walked by the site build. tsconfig excludes it; renders run manually via cd remotion && npm run render.
  • Reusable <VideoEmbed> component (poster-first, preload=none, click-to-play).
  • Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
  • 5 clips embedded into the business page (setup, self-service, add-card, retry-to-recovery, notifications), sequenced from the real product screenshots via the Reel component — not synthetic mockups.

#158913 — screenshots

  • 8 real betabulk captures (John Doe subs): cards-02-add-card, portal-01-summary-active (replaces the wrong mockup flagged in 158909 :: docs: AutoPay public documentation #169), portal-02-trialing, portal-03-canceled-pending-reactivation, portal-04-expired (new — the Expired step had no image), portal-05-no-cards, recovery-01-past-due, states-03-magic-link-invalid.
  • Asset manifest under static/img/business/autopay/MANIFEST.md, which records for every asset whether it is a real capture or one of Menna's mockups, and why.

What is still a mockup (all listed in MANIFEST.md, none blocking this PR)

  • The three cancel/reactivate modal dialogs — the subs exist and portal-03 was captured from one, but the dialogs need an interactive click on the live portal, which was not viable here (CDP Page.captureScreenshot times out; the extension viewport caps at 360px). Capture via Menna or a follow-up session; the sub URLs are ready.
  • recovery-02-payment-confirmed — needs a completed payment (card entry).
  • states-01/02/04, notifications-01..06.
  • Consequently two clips still contain some mockup frames: retry-to-recovery (recovery-02) and notification-emails (notifications-01/03/05).

Copy alignment with Ankit's clip scripts (#158914 R5) is still worth a pass before these are treated as final.


Description corrected 2026-08-18 after @claude's review. The earlier body said the 5 clips were "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914)" and that a portal-01 recapture was pending. That was written before 38bf32a, which recaptured portal-01 and rebuilt every clip from the real screenshots, so the note described a state the branch had already moved past — and the TODO markers the review correctly could not find were never added because they had stopped being true. Adding them now would label real captures as provisional.

junaidsarfrazdevand others added 4 commits August 13, 2026 19:26
…, #158914)
Adds the video + screenshot assets on top of the AutoPay docs merged in #169.
#158914 — Remotion video pipeline:
- Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never
installed by npm ci nor walked by the site build. tsconfig excludes it; renders
run manually via `cd remotion && npm run render`.
- Reusable <VideoEmbed> component (poster-first, preload=none, reduced-motion safe).
- Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
- 5 first-cut clips embedded into the business page (setup, self-service, add-card,
retry-to-recovery, notifications).
#158913 — screenshots:
- cards-02-add-card.png captured from betabulk (John Doe), fills the add-card gap.
- Asset manifest under static/img/business/autopay/MANIFEST.md.
NOTE: the 5 clips are FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each
composition, the business page, and remotion/README.md. They must be revisited and
re-recorded once the betabulk AutoPay scenario URLs are available, with copy aligned
to Ankit's clip scripts (#158914 R5). portal-01 recapture (flagged in #169) also pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#158913, #158914)
Replaces mockups with real customer-portal captures (John Doe / betabulk) and
rebuilds the Remotion clips to sequence those real screenshots.
Screenshots (#158913) — 7 real betabulk captures now in the business-page sliders:
portal-01-summary-active (replaces the flagged wrong mockup), portal-02-trialing,
portal-03-canceled-pending-reactivation, portal-04-expired (new + wired into the
previously image-less Expired step), portal-05-no-cards, recovery-01-past-due,
states-03-magic-link-invalid. Kept as mockups (see MANIFEST.md): the three
cancel/reactivate dialogs, recovery-02, states-01/02/04, notifications-01..06.
Videos (#158914) — rebuilt from the real screenshots: new Reel component sequences
the real PNGs (staticFile from remotion/public/screens, copied by render-all.mjs,
gitignored) with captions + crossfades; all 5 clips re-rendered.
typecheck + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@junaidsarfrazdev
junaidsarfrazdev marked this pull request as ready for review August 18, 2026 13:51
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 44s —— View job


Claude finished the review

Todo list:

  • Gather context (PR diff, changed files, CLAUDE.md)
  • Review remotion/ workspace isolation (package.json, tsconfig, gitignore)
  • Review VideoEmbed component
  • Review AutoPay docs page changes
  • Review asset manifest / screenshots
  • Post final review

Summary

Solid, well-scoped PR. The remotion/ isolation is done carefully (own package.json/tsconfig/lockfile, remotion/node_modules|out|public gitignored, root tsconfig.json excludes it, README.md explicitly documents why npm ci/typecheck/build never touch it). VideoEmbed is a clean poster-first, click-to-play component (preload="none", respects prefers-reduced-motion, dark-mode aware CSS). The five compositions accurately match what's described in static/img/business/autopay/MANIFEST.md, and all referenced image/video paths in docs/business/autopay/index.md resolve to real committed files.

Finding

PR description says the placeholder flags are missing from the diff. The PR body states the 5 clips are "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each composition, the business page, and remotion/README.md." I grepped the full diff (compositions, Root.tsx, docs/business/autopay/index.md, remotion/README.md) for TODO(#158914), placeholder, and first-cut — none of these markers actually exist anywhere in the changed files. Right now a reader of docs/business/autopay/index.md or remotion/src/compositions/*.tsx has no signal that these 5 videos are provisional and pending re-recording against real betabulk scenario URLs + Ankit's clip scripts. Since this page ships to real merchants, worth either adding the flags as described or updating the PR description to match reality.

Fix this →

Minor / non-blocking

  • src/components/VideoEmbed/index.tsx:44-54 — when prefers-reduced-motion is set, clicking the poster swaps in the <video> with autoPlay={false}, so the user has to click twice (once on the custom poster button, once on the native play control) to actually start playback. Reasonable accessibility-first tradeoff, just noting the double-click UX.
  • Couldn't run npm run typecheck / npm run build myself — Bash execution required interactive approval in this environment that wasn't granted. Given the isolation approach is thoroughly documented and cross-checked in remotion/README.md (including "verified: a deliberate type error inside remotion/ does not fail the root typecheck"), I'd suggest CI confirm this rather than re-deriving it manually.
    · branch: task/158913-158914-autopay-assets

`autoPlay={!reduced}` meant a reader with `prefers-reduced-motion` clicked the
poster, got a paused `<video>`, and had to click the native control to actually
start it. That gate misreads the preference: it governs UNSOLICITED motion, and
`playing` only becomes true from the poster click, so playback here is always
user-initiated.
Autoplay is unconditional now, which makes `usePrefersReducedMotion` dead — the
hook existed for that one prop, so it goes with it.
Raised as a non-blocking note by @claude on PR #171.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Thanks — the finding was correct, but the fix is the other branch of what you offered.

The TODO(#158914) markers are genuinely absent, and should stay absent. They were never added because they stopped being true: 38bf32a (17 Aug) recaptured portal-01 and rebuilt all 5 clips from the real betabulk screenshots via the new Reel component. The PR body still carried the pre-rebuild note, so it described a state the branch had already moved past. Adding "first-cut placeholder" flags now would label real captures as provisional — the opposite of accurate.

The branch already documents this, which is worth checking against next time the two disagree:

  • static/img/business/autopay/MANIFEST.md § "Videos (#158914) — rebuilt from the REAL screenshots"
  • remotion/README.md, first line: "Clips are built from the REAL product screenshots."

So I've corrected the PR description instead, and it now also records what genuinely is still a mockup — the three cancel/reactivate modal dialogs (need an interactive click on the live portal), recovery-02, states-01/02/04, notifications-01..06 — and therefore that two clips still contain some mockup frames. That was the real gap: the honest caveat existed in MANIFEST.md but not in the PR.

Minor finding — fixed in 152610a. You were right that reduced-motion caused a double click. The gate also misread the preference: prefers-reduced-motion governs unsolicited motion, and playing only becomes true from the poster click, so playback there is always user-initiated. autoPlay is unconditional now, and usePrefersReducedMotion went with it since it existed for that one prop. npm run typecheck green.

On the third point — CI is the right place to confirm the remotion/ isolation, agreed. npm run typecheck passes locally after this change.

@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 28s —— View job


Claude finished re-reviewing @junaidsarfrazdev's PR

Todo list:

  • Gather context (PR diff, prior review discussion, CLAUDE.md)
  • Verify the 152610a fix (double-click / prefers-reduced-motion change) in VideoEmbed
  • Verify the PR description correction matches MANIFEST.md / README.md
  • Re-check remaining files (compositions, docs page, manifest) for anything new
  • Post final review

Summary

Both follow-ups from the previous review are handled correctly:

  • PR description: now accurately reflects that all 5 clips are rebuilt from real betabulk screenshots (not first-cut placeholders), and lists the genuine remaining mockups (3 modal dialogs, recovery-02, states-01/02/04, notifications-01..06). This matches static/img/business/autopay/MANIFEST.md and remotion/README.md, and docs/business/autopay/index.md's in-page comment was updated to match (git diff 9ca313e..HEAD -- docs/business/autopay/index.md) — the stale TODO(#158914) "FIRST-CUT PLACEHOLDERS" comment is gone, replaced with an accurate "built from the real betabulk screenshots" note.
  • 152610a: the fix itself is correct — playing only flips true from the poster's own click handler (src/components/VideoEmbed/index.tsx:51), so gating autoPlay on prefers-reduced-motion was never actually suppressing unsolicited motion, just adding a redundant second click. Making autoPlay unconditional and dropping the now-dead usePrefersReducedMotion hook is the right call, and the inline comment explains the non-obvious "why."

Finding

src/components/VideoEmbed/README.md:36-37 documents the behavior 152610a just removed. It still reads:

Reduced motion. When the OS requests reduced motion, the video does not autoplay after the click (autoPlay={!reduced}); the reader controls playback.

autoPlay={!reduced} and the reduced state no longer exist in index.tsxautoPlay is now unconditional. A future reader of this component's own README would be told about behavior that isn't there anymore, and would be citing dead code ({!reduced}) if they went looking for it.

Fix this →

Minor / non-blocking

  • docs/superpowers/plans/2026-08-12-autopay-assets-docs.md and docs/superpowers/specs/2026-08-12-autopay-assets-docs-design.md also mention usePrefersReducedMotion, but these are dated planning artifacts (design history), not live component docs — I wouldn't touch them.
  • Same limitation as the last review: couldn't run npm run typecheck myself (Bash execution needs interactive approval that wasn't granted here). You noted it's green locally after 152610a; I'd still lean on CI to confirm.

Everything else — the remotion/ isolation, the manifest's real-vs-mockup accounting, and the docs page's image/video paths — is unchanged since the last pass and still checks out.
· branch: task/158913-158914-autopay-assets

…emoved
It still documented `autoPlay={!reduced}` and a `reduced` state, neither of
which exists — so the component's own README sent a reader looking for deleted
code. Replaced with what the code does now, and why it is not a reduced-motion
violation: the `<video>` only mounts from the poster's click handler, so
playback is always user-initiated.
Caught by @claude on PR #171. I had grepped `index.tsx` for the hook when
removing it, but not the component's README beside it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Good catch — fixed in 70d02d0.

src/components/VideoEmbed/README.md still documented autoPlay={!reduced} and a reduced state, so the component's own README was pointing a reader at code deleted in 152610a. It now describes what the code does and why it isn't a reduced-motion violation: the <video> only mounts from the poster's click handler, so playback is always user-initiated.

My miss — when removing the hook I grepped index.tsx for it but not the README sitting beside it. I've swept the rest: no live reference to usePrefersReducedMotion or {!reduced} remains outside the dated planning artifacts.

Agreed on both minor points. The docs/superpowers/plans|specs files are design history from 2026-08-12 and should keep saying what was decided then — rewriting them would falsify the record. And npm run typecheck is green locally after both commits; CI is the right place to confirm that and the remotion/ isolation.

One thing worth recording since it isn't visible from the diff: I could not verify playback end-to-end in a browser. The clips don't decode in the Chrome available here — opening setup-subscription.mp4 directly, with no React involved, hangs at readyState 0 / videoWidth 0 with no error, though canPlayType('video/mp4; codecs="avc1.42E01E") reports probably. The files themselves are fine — valid faststart MP4 (moov before mdat), served 200 video/mp4, 540 KB — so this reads as a Linux Chromium build whose canPlayType over-reports while the proprietary H.264 decoder is absent, not a defect in the assets or the component. Someone should click through the five embeds on a normal browser before merge; the component behaviour either side of that is verified (poster-first, no <video> in the DOM until the click, then mounted with autoplay + muted and no second click needed).

@junaidsarfrazdev
junaidsarfrazdev merged commit 2aa9a7d into devAug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@junaidsarfrazdev
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat(autopay): Remotion video pipeline + add-card screenshot (#158913… by junaidsarfrazdev · Pull Request #171 · ottuco/docs · GitHub
Skip to content

feat(autopay): Remotion video pipeline + add-card screenshot (#158913… - #171

Merged
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets
Aug 18, 2026
Merged

feat(autopay): Remotion video pipeline + add-card screenshot (#158913…#171
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets

Conversation

@junaidsarfrazdev

@junaidsarfrazdevjunaidsarfrazdev commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds the video + screenshot assets on top of the AutoPay docs merged in #169.

#158914 — Remotion video pipeline

  • Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never installed by npm ci nor walked by the site build. tsconfig excludes it; renders run manually via cd remotion && npm run render.
  • Reusable <VideoEmbed> component (poster-first, preload=none, click-to-play).
  • Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
  • 5 clips embedded into the business page (setup, self-service, add-card, retry-to-recovery, notifications), sequenced from the real product screenshots via the Reel component — not synthetic mockups.

#158913 — screenshots

  • 8 real betabulk captures (John Doe subs): cards-02-add-card, portal-01-summary-active (replaces the wrong mockup flagged in 158909 :: docs: AutoPay public documentation #169), portal-02-trialing, portal-03-canceled-pending-reactivation, portal-04-expired (new — the Expired step had no image), portal-05-no-cards, recovery-01-past-due, states-03-magic-link-invalid.
  • Asset manifest under static/img/business/autopay/MANIFEST.md, which records for every asset whether it is a real capture or one of Menna's mockups, and why.

What is still a mockup (all listed in MANIFEST.md, none blocking this PR)

  • The three cancel/reactivate modal dialogs — the subs exist and portal-03 was captured from one, but the dialogs need an interactive click on the live portal, which was not viable here (CDP Page.captureScreenshot times out; the extension viewport caps at 360px). Capture via Menna or a follow-up session; the sub URLs are ready.
  • recovery-02-payment-confirmed — needs a completed payment (card entry).
  • states-01/02/04, notifications-01..06.
  • Consequently two clips still contain some mockup frames: retry-to-recovery (recovery-02) and notification-emails (notifications-01/03/05).

Copy alignment with Ankit's clip scripts (#158914 R5) is still worth a pass before these are treated as final.


Description corrected 2026-08-18 after @claude's review. The earlier body said the 5 clips were "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914)" and that a portal-01 recapture was pending. That was written before 38bf32a, which recaptured portal-01 and rebuilt every clip from the real screenshots, so the note described a state the branch had already moved past — and the TODO markers the review correctly could not find were never added because they had stopped being true. Adding them now would label real captures as provisional.

junaidsarfrazdevand others added 4 commits August 13, 2026 19:26
…, #158914)
Adds the video + screenshot assets on top of the AutoPay docs merged in #169.
#158914 — Remotion video pipeline:
- Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never
installed by npm ci nor walked by the site build. tsconfig excludes it; renders
run manually via `cd remotion && npm run render`.
- Reusable <VideoEmbed> component (poster-first, preload=none, reduced-motion safe).
- Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
- 5 first-cut clips embedded into the business page (setup, self-service, add-card,
retry-to-recovery, notifications).
#158913 — screenshots:
- cards-02-add-card.png captured from betabulk (John Doe), fills the add-card gap.
- Asset manifest under static/img/business/autopay/MANIFEST.md.
NOTE: the 5 clips are FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each
composition, the business page, and remotion/README.md. They must be revisited and
re-recorded once the betabulk AutoPay scenario URLs are available, with copy aligned
to Ankit's clip scripts (#158914 R5). portal-01 recapture (flagged in #169) also pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#158913, #158914)
Replaces mockups with real customer-portal captures (John Doe / betabulk) and
rebuilds the Remotion clips to sequence those real screenshots.
Screenshots (#158913) — 7 real betabulk captures now in the business-page sliders:
portal-01-summary-active (replaces the flagged wrong mockup), portal-02-trialing,
portal-03-canceled-pending-reactivation, portal-04-expired (new + wired into the
previously image-less Expired step), portal-05-no-cards, recovery-01-past-due,
states-03-magic-link-invalid. Kept as mockups (see MANIFEST.md): the three
cancel/reactivate dialogs, recovery-02, states-01/02/04, notifications-01..06.
Videos (#158914) — rebuilt from the real screenshots: new Reel component sequences
the real PNGs (staticFile from remotion/public/screens, copied by render-all.mjs,
gitignored) with captions + crossfades; all 5 clips re-rendered.
typecheck + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@junaidsarfrazdev
junaidsarfrazdev marked this pull request as ready for review August 18, 2026 13:51
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 44s —— View job


Claude finished the review

Todo list:

  • Gather context (PR diff, changed files, CLAUDE.md)
  • Review remotion/ workspace isolation (package.json, tsconfig, gitignore)
  • Review VideoEmbed component
  • Review AutoPay docs page changes
  • Review asset manifest / screenshots
  • Post final review

Summary

Solid, well-scoped PR. The remotion/ isolation is done carefully (own package.json/tsconfig/lockfile, remotion/node_modules|out|public gitignored, root tsconfig.json excludes it, README.md explicitly documents why npm ci/typecheck/build never touch it). VideoEmbed is a clean poster-first, click-to-play component (preload="none", respects prefers-reduced-motion, dark-mode aware CSS). The five compositions accurately match what's described in static/img/business/autopay/MANIFEST.md, and all referenced image/video paths in docs/business/autopay/index.md resolve to real committed files.

Finding

PR description says the placeholder flags are missing from the diff. The PR body states the 5 clips are "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each composition, the business page, and remotion/README.md." I grepped the full diff (compositions, Root.tsx, docs/business/autopay/index.md, remotion/README.md) for TODO(#158914), placeholder, and first-cut — none of these markers actually exist anywhere in the changed files. Right now a reader of docs/business/autopay/index.md or remotion/src/compositions/*.tsx has no signal that these 5 videos are provisional and pending re-recording against real betabulk scenario URLs + Ankit's clip scripts. Since this page ships to real merchants, worth either adding the flags as described or updating the PR description to match reality.

Fix this →

Minor / non-blocking

  • src/components/VideoEmbed/index.tsx:44-54 — when prefers-reduced-motion is set, clicking the poster swaps in the <video> with autoPlay={false}, so the user has to click twice (once on the custom poster button, once on the native play control) to actually start playback. Reasonable accessibility-first tradeoff, just noting the double-click UX.
  • Couldn't run npm run typecheck / npm run build myself — Bash execution required interactive approval in this environment that wasn't granted. Given the isolation approach is thoroughly documented and cross-checked in remotion/README.md (including "verified: a deliberate type error inside remotion/ does not fail the root typecheck"), I'd suggest CI confirm this rather than re-deriving it manually.
    · branch: task/158913-158914-autopay-assets

`autoPlay={!reduced}` meant a reader with `prefers-reduced-motion` clicked the
poster, got a paused `<video>`, and had to click the native control to actually
start it. That gate misreads the preference: it governs UNSOLICITED motion, and
`playing` only becomes true from the poster click, so playback here is always
user-initiated.
Autoplay is unconditional now, which makes `usePrefersReducedMotion` dead — the
hook existed for that one prop, so it goes with it.
Raised as a non-blocking note by @claude on PR #171.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Thanks — the finding was correct, but the fix is the other branch of what you offered.

The TODO(#158914) markers are genuinely absent, and should stay absent. They were never added because they stopped being true: 38bf32a (17 Aug) recaptured portal-01 and rebuilt all 5 clips from the real betabulk screenshots via the new Reel component. The PR body still carried the pre-rebuild note, so it described a state the branch had already moved past. Adding "first-cut placeholder" flags now would label real captures as provisional — the opposite of accurate.

The branch already documents this, which is worth checking against next time the two disagree:

  • static/img/business/autopay/MANIFEST.md § "Videos (#158914) — rebuilt from the REAL screenshots"
  • remotion/README.md, first line: "Clips are built from the REAL product screenshots."

So I've corrected the PR description instead, and it now also records what genuinely is still a mockup — the three cancel/reactivate modal dialogs (need an interactive click on the live portal), recovery-02, states-01/02/04, notifications-01..06 — and therefore that two clips still contain some mockup frames. That was the real gap: the honest caveat existed in MANIFEST.md but not in the PR.

Minor finding — fixed in 152610a. You were right that reduced-motion caused a double click. The gate also misread the preference: prefers-reduced-motion governs unsolicited motion, and playing only becomes true from the poster click, so playback there is always user-initiated. autoPlay is unconditional now, and usePrefersReducedMotion went with it since it existed for that one prop. npm run typecheck green.

On the third point — CI is the right place to confirm the remotion/ isolation, agreed. npm run typecheck passes locally after this change.

@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 28s —— View job


Claude finished re-reviewing @junaidsarfrazdev's PR

Todo list:

  • Gather context (PR diff, prior review discussion, CLAUDE.md)
  • Verify the 152610a fix (double-click / prefers-reduced-motion change) in VideoEmbed
  • Verify the PR description correction matches MANIFEST.md / README.md
  • Re-check remaining files (compositions, docs page, manifest) for anything new
  • Post final review

Summary

Both follow-ups from the previous review are handled correctly:

  • PR description: now accurately reflects that all 5 clips are rebuilt from real betabulk screenshots (not first-cut placeholders), and lists the genuine remaining mockups (3 modal dialogs, recovery-02, states-01/02/04, notifications-01..06). This matches static/img/business/autopay/MANIFEST.md and remotion/README.md, and docs/business/autopay/index.md's in-page comment was updated to match (git diff 9ca313e..HEAD -- docs/business/autopay/index.md) — the stale TODO(#158914) "FIRST-CUT PLACEHOLDERS" comment is gone, replaced with an accurate "built from the real betabulk screenshots" note.
  • 152610a: the fix itself is correct — playing only flips true from the poster's own click handler (src/components/VideoEmbed/index.tsx:51), so gating autoPlay on prefers-reduced-motion was never actually suppressing unsolicited motion, just adding a redundant second click. Making autoPlay unconditional and dropping the now-dead usePrefersReducedMotion hook is the right call, and the inline comment explains the non-obvious "why."

Finding

src/components/VideoEmbed/README.md:36-37 documents the behavior 152610a just removed. It still reads:

Reduced motion. When the OS requests reduced motion, the video does not autoplay after the click (autoPlay={!reduced}); the reader controls playback.

autoPlay={!reduced} and the reduced state no longer exist in index.tsxautoPlay is now unconditional. A future reader of this component's own README would be told about behavior that isn't there anymore, and would be citing dead code ({!reduced}) if they went looking for it.

Fix this →

Minor / non-blocking

  • docs/superpowers/plans/2026-08-12-autopay-assets-docs.md and docs/superpowers/specs/2026-08-12-autopay-assets-docs-design.md also mention usePrefersReducedMotion, but these are dated planning artifacts (design history), not live component docs — I wouldn't touch them.
  • Same limitation as the last review: couldn't run npm run typecheck myself (Bash execution needs interactive approval that wasn't granted here). You noted it's green locally after 152610a; I'd still lean on CI to confirm.

Everything else — the remotion/ isolation, the manifest's real-vs-mockup accounting, and the docs page's image/video paths — is unchanged since the last pass and still checks out.
· branch: task/158913-158914-autopay-assets

…emoved
It still documented `autoPlay={!reduced}` and a `reduced` state, neither of
which exists — so the component's own README sent a reader looking for deleted
code. Replaced with what the code does now, and why it is not a reduced-motion
violation: the `<video>` only mounts from the poster's click handler, so
playback is always user-initiated.
Caught by @claude on PR #171. I had grepped `index.tsx` for the hook when
removing it, but not the component's README beside it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Good catch — fixed in 70d02d0.

src/components/VideoEmbed/README.md still documented autoPlay={!reduced} and a reduced state, so the component's own README was pointing a reader at code deleted in 152610a. It now describes what the code does and why it isn't a reduced-motion violation: the <video> only mounts from the poster's click handler, so playback is always user-initiated.

My miss — when removing the hook I grepped index.tsx for it but not the README sitting beside it. I've swept the rest: no live reference to usePrefersReducedMotion or {!reduced} remains outside the dated planning artifacts.

Agreed on both minor points. The docs/superpowers/plans|specs files are design history from 2026-08-12 and should keep saying what was decided then — rewriting them would falsify the record. And npm run typecheck is green locally after both commits; CI is the right place to confirm that and the remotion/ isolation.

One thing worth recording since it isn't visible from the diff: I could not verify playback end-to-end in a browser. The clips don't decode in the Chrome available here — opening setup-subscription.mp4 directly, with no React involved, hangs at readyState 0 / videoWidth 0 with no error, though canPlayType('video/mp4; codecs="avc1.42E01E") reports probably. The files themselves are fine — valid faststart MP4 (moov before mdat), served 200 video/mp4, 540 KB — so this reads as a Linux Chromium build whose canPlayType over-reports while the proprietary H.264 decoder is absent, not a defect in the assets or the component. Someone should click through the five embeds on a normal browser before merge; the component behaviour either side of that is verified (poster-first, no <video> in the DOM until the click, then mounted with autoplay + muted and no second click needed).

@junaidsarfrazdev
junaidsarfrazdev merged commit 2aa9a7d into devAug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@junaidsarfrazdev
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(autopay): Remotion video pipeline + add-card screenshot (#158913… by junaidsarfrazdev · Pull Request #171 · ottuco/docs · GitHub
Skip to content

feat(autopay): Remotion video pipeline + add-card screenshot (#158913… - #171

Merged
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets
Aug 18, 2026
Merged

feat(autopay): Remotion video pipeline + add-card screenshot (#158913…#171
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets

Conversation

@junaidsarfrazdev

@junaidsarfrazdevjunaidsarfrazdev commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds the video + screenshot assets on top of the AutoPay docs merged in #169.

#158914 — Remotion video pipeline

  • Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never installed by npm ci nor walked by the site build. tsconfig excludes it; renders run manually via cd remotion && npm run render.
  • Reusable <VideoEmbed> component (poster-first, preload=none, click-to-play).
  • Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
  • 5 clips embedded into the business page (setup, self-service, add-card, retry-to-recovery, notifications), sequenced from the real product screenshots via the Reel component — not synthetic mockups.

#158913 — screenshots

  • 8 real betabulk captures (John Doe subs): cards-02-add-card, portal-01-summary-active (replaces the wrong mockup flagged in 158909 :: docs: AutoPay public documentation #169), portal-02-trialing, portal-03-canceled-pending-reactivation, portal-04-expired (new — the Expired step had no image), portal-05-no-cards, recovery-01-past-due, states-03-magic-link-invalid.
  • Asset manifest under static/img/business/autopay/MANIFEST.md, which records for every asset whether it is a real capture or one of Menna's mockups, and why.

What is still a mockup (all listed in MANIFEST.md, none blocking this PR)

  • The three cancel/reactivate modal dialogs — the subs exist and portal-03 was captured from one, but the dialogs need an interactive click on the live portal, which was not viable here (CDP Page.captureScreenshot times out; the extension viewport caps at 360px). Capture via Menna or a follow-up session; the sub URLs are ready.
  • recovery-02-payment-confirmed — needs a completed payment (card entry).
  • states-01/02/04, notifications-01..06.
  • Consequently two clips still contain some mockup frames: retry-to-recovery (recovery-02) and notification-emails (notifications-01/03/05).

Copy alignment with Ankit's clip scripts (#158914 R5) is still worth a pass before these are treated as final.


Description corrected 2026-08-18 after @claude's review. The earlier body said the 5 clips were "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914)" and that a portal-01 recapture was pending. That was written before 38bf32a, which recaptured portal-01 and rebuilt every clip from the real screenshots, so the note described a state the branch had already moved past — and the TODO markers the review correctly could not find were never added because they had stopped being true. Adding them now would label real captures as provisional.

junaidsarfrazdevand others added 4 commits August 13, 2026 19:26
…, #158914)
Adds the video + screenshot assets on top of the AutoPay docs merged in #169.
#158914 — Remotion video pipeline:
- Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never
installed by npm ci nor walked by the site build. tsconfig excludes it; renders
run manually via `cd remotion && npm run render`.
- Reusable <VideoEmbed> component (poster-first, preload=none, reduced-motion safe).
- Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
- 5 first-cut clips embedded into the business page (setup, self-service, add-card,
retry-to-recovery, notifications).
#158913 — screenshots:
- cards-02-add-card.png captured from betabulk (John Doe), fills the add-card gap.
- Asset manifest under static/img/business/autopay/MANIFEST.md.
NOTE: the 5 clips are FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each
composition, the business page, and remotion/README.md. They must be revisited and
re-recorded once the betabulk AutoPay scenario URLs are available, with copy aligned
to Ankit's clip scripts (#158914 R5). portal-01 recapture (flagged in #169) also pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#158913, #158914)
Replaces mockups with real customer-portal captures (John Doe / betabulk) and
rebuilds the Remotion clips to sequence those real screenshots.
Screenshots (#158913) — 7 real betabulk captures now in the business-page sliders:
portal-01-summary-active (replaces the flagged wrong mockup), portal-02-trialing,
portal-03-canceled-pending-reactivation, portal-04-expired (new + wired into the
previously image-less Expired step), portal-05-no-cards, recovery-01-past-due,
states-03-magic-link-invalid. Kept as mockups (see MANIFEST.md): the three
cancel/reactivate dialogs, recovery-02, states-01/02/04, notifications-01..06.
Videos (#158914) — rebuilt from the real screenshots: new Reel component sequences
the real PNGs (staticFile from remotion/public/screens, copied by render-all.mjs,
gitignored) with captions + crossfades; all 5 clips re-rendered.
typecheck + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@junaidsarfrazdev
junaidsarfrazdev marked this pull request as ready for review August 18, 2026 13:51
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 44s —— View job


Claude finished the review

Todo list:

  • Gather context (PR diff, changed files, CLAUDE.md)
  • Review remotion/ workspace isolation (package.json, tsconfig, gitignore)
  • Review VideoEmbed component
  • Review AutoPay docs page changes
  • Review asset manifest / screenshots
  • Post final review

Summary

Solid, well-scoped PR. The remotion/ isolation is done carefully (own package.json/tsconfig/lockfile, remotion/node_modules|out|public gitignored, root tsconfig.json excludes it, README.md explicitly documents why npm ci/typecheck/build never touch it). VideoEmbed is a clean poster-first, click-to-play component (preload="none", respects prefers-reduced-motion, dark-mode aware CSS). The five compositions accurately match what's described in static/img/business/autopay/MANIFEST.md, and all referenced image/video paths in docs/business/autopay/index.md resolve to real committed files.

Finding

PR description says the placeholder flags are missing from the diff. The PR body states the 5 clips are "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each composition, the business page, and remotion/README.md." I grepped the full diff (compositions, Root.tsx, docs/business/autopay/index.md, remotion/README.md) for TODO(#158914), placeholder, and first-cut — none of these markers actually exist anywhere in the changed files. Right now a reader of docs/business/autopay/index.md or remotion/src/compositions/*.tsx has no signal that these 5 videos are provisional and pending re-recording against real betabulk scenario URLs + Ankit's clip scripts. Since this page ships to real merchants, worth either adding the flags as described or updating the PR description to match reality.

Fix this →

Minor / non-blocking

  • src/components/VideoEmbed/index.tsx:44-54 — when prefers-reduced-motion is set, clicking the poster swaps in the <video> with autoPlay={false}, so the user has to click twice (once on the custom poster button, once on the native play control) to actually start playback. Reasonable accessibility-first tradeoff, just noting the double-click UX.
  • Couldn't run npm run typecheck / npm run build myself — Bash execution required interactive approval in this environment that wasn't granted. Given the isolation approach is thoroughly documented and cross-checked in remotion/README.md (including "verified: a deliberate type error inside remotion/ does not fail the root typecheck"), I'd suggest CI confirm this rather than re-deriving it manually.
    · branch: task/158913-158914-autopay-assets

`autoPlay={!reduced}` meant a reader with `prefers-reduced-motion` clicked the
poster, got a paused `<video>`, and had to click the native control to actually
start it. That gate misreads the preference: it governs UNSOLICITED motion, and
`playing` only becomes true from the poster click, so playback here is always
user-initiated.
Autoplay is unconditional now, which makes `usePrefersReducedMotion` dead — the
hook existed for that one prop, so it goes with it.
Raised as a non-blocking note by @claude on PR #171.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Thanks — the finding was correct, but the fix is the other branch of what you offered.

The TODO(#158914) markers are genuinely absent, and should stay absent. They were never added because they stopped being true: 38bf32a (17 Aug) recaptured portal-01 and rebuilt all 5 clips from the real betabulk screenshots via the new Reel component. The PR body still carried the pre-rebuild note, so it described a state the branch had already moved past. Adding "first-cut placeholder" flags now would label real captures as provisional — the opposite of accurate.

The branch already documents this, which is worth checking against next time the two disagree:

  • static/img/business/autopay/MANIFEST.md § "Videos (#158914) — rebuilt from the REAL screenshots"
  • remotion/README.md, first line: "Clips are built from the REAL product screenshots."

So I've corrected the PR description instead, and it now also records what genuinely is still a mockup — the three cancel/reactivate modal dialogs (need an interactive click on the live portal), recovery-02, states-01/02/04, notifications-01..06 — and therefore that two clips still contain some mockup frames. That was the real gap: the honest caveat existed in MANIFEST.md but not in the PR.

Minor finding — fixed in 152610a. You were right that reduced-motion caused a double click. The gate also misread the preference: prefers-reduced-motion governs unsolicited motion, and playing only becomes true from the poster click, so playback there is always user-initiated. autoPlay is unconditional now, and usePrefersReducedMotion went with it since it existed for that one prop. npm run typecheck green.

On the third point — CI is the right place to confirm the remotion/ isolation, agreed. npm run typecheck passes locally after this change.

@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 28s —— View job


Claude finished re-reviewing @junaidsarfrazdev's PR

Todo list:

  • Gather context (PR diff, prior review discussion, CLAUDE.md)
  • Verify the 152610a fix (double-click / prefers-reduced-motion change) in VideoEmbed
  • Verify the PR description correction matches MANIFEST.md / README.md
  • Re-check remaining files (compositions, docs page, manifest) for anything new
  • Post final review

Summary

Both follow-ups from the previous review are handled correctly:

  • PR description: now accurately reflects that all 5 clips are rebuilt from real betabulk screenshots (not first-cut placeholders), and lists the genuine remaining mockups (3 modal dialogs, recovery-02, states-01/02/04, notifications-01..06). This matches static/img/business/autopay/MANIFEST.md and remotion/README.md, and docs/business/autopay/index.md's in-page comment was updated to match (git diff 9ca313e..HEAD -- docs/business/autopay/index.md) — the stale TODO(#158914) "FIRST-CUT PLACEHOLDERS" comment is gone, replaced with an accurate "built from the real betabulk screenshots" note.
  • 152610a: the fix itself is correct — playing only flips true from the poster's own click handler (src/components/VideoEmbed/index.tsx:51), so gating autoPlay on prefers-reduced-motion was never actually suppressing unsolicited motion, just adding a redundant second click. Making autoPlay unconditional and dropping the now-dead usePrefersReducedMotion hook is the right call, and the inline comment explains the non-obvious "why."

Finding

src/components/VideoEmbed/README.md:36-37 documents the behavior 152610a just removed. It still reads:

Reduced motion. When the OS requests reduced motion, the video does not autoplay after the click (autoPlay={!reduced}); the reader controls playback.

autoPlay={!reduced} and the reduced state no longer exist in index.tsxautoPlay is now unconditional. A future reader of this component's own README would be told about behavior that isn't there anymore, and would be citing dead code ({!reduced}) if they went looking for it.

Fix this →

Minor / non-blocking

  • docs/superpowers/plans/2026-08-12-autopay-assets-docs.md and docs/superpowers/specs/2026-08-12-autopay-assets-docs-design.md also mention usePrefersReducedMotion, but these are dated planning artifacts (design history), not live component docs — I wouldn't touch them.
  • Same limitation as the last review: couldn't run npm run typecheck myself (Bash execution needs interactive approval that wasn't granted here). You noted it's green locally after 152610a; I'd still lean on CI to confirm.

Everything else — the remotion/ isolation, the manifest's real-vs-mockup accounting, and the docs page's image/video paths — is unchanged since the last pass and still checks out.
· branch: task/158913-158914-autopay-assets

…emoved
It still documented `autoPlay={!reduced}` and a `reduced` state, neither of
which exists — so the component's own README sent a reader looking for deleted
code. Replaced with what the code does now, and why it is not a reduced-motion
violation: the `<video>` only mounts from the poster's click handler, so
playback is always user-initiated.
Caught by @claude on PR #171. I had grepped `index.tsx` for the hook when
removing it, but not the component's README beside it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Good catch — fixed in 70d02d0.

src/components/VideoEmbed/README.md still documented autoPlay={!reduced} and a reduced state, so the component's own README was pointing a reader at code deleted in 152610a. It now describes what the code does and why it isn't a reduced-motion violation: the <video> only mounts from the poster's click handler, so playback is always user-initiated.

My miss — when removing the hook I grepped index.tsx for it but not the README sitting beside it. I've swept the rest: no live reference to usePrefersReducedMotion or {!reduced} remains outside the dated planning artifacts.

Agreed on both minor points. The docs/superpowers/plans|specs files are design history from 2026-08-12 and should keep saying what was decided then — rewriting them would falsify the record. And npm run typecheck is green locally after both commits; CI is the right place to confirm that and the remotion/ isolation.

One thing worth recording since it isn't visible from the diff: I could not verify playback end-to-end in a browser. The clips don't decode in the Chrome available here — opening setup-subscription.mp4 directly, with no React involved, hangs at readyState 0 / videoWidth 0 with no error, though canPlayType('video/mp4; codecs="avc1.42E01E") reports probably. The files themselves are fine — valid faststart MP4 (moov before mdat), served 200 video/mp4, 540 KB — so this reads as a Linux Chromium build whose canPlayType over-reports while the proprietary H.264 decoder is absent, not a defect in the assets or the component. Someone should click through the five embeds on a normal browser before merge; the component behaviour either side of that is verified (poster-first, no <video> in the DOM until the click, then mounted with autoplay + muted and no second click needed).

@junaidsarfrazdev
junaidsarfrazdev merged commit 2aa9a7d into devAug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@junaidsarfrazdev
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(autopay): Remotion video pipeline + add-card screenshot (#158913… by junaidsarfrazdev · Pull Request #171 · ottuco/docs · GitHub
Skip to content

feat(autopay): Remotion video pipeline + add-card screenshot (#158913… - #171

Merged
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets
Aug 18, 2026
Merged

feat(autopay): Remotion video pipeline + add-card screenshot (#158913…#171
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets

Conversation

@junaidsarfrazdev

@junaidsarfrazdevjunaidsarfrazdev commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds the video + screenshot assets on top of the AutoPay docs merged in #169.

#158914 — Remotion video pipeline

  • Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never installed by npm ci nor walked by the site build. tsconfig excludes it; renders run manually via cd remotion && npm run render.
  • Reusable <VideoEmbed> component (poster-first, preload=none, click-to-play).
  • Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
  • 5 clips embedded into the business page (setup, self-service, add-card, retry-to-recovery, notifications), sequenced from the real product screenshots via the Reel component — not synthetic mockups.

#158913 — screenshots

  • 8 real betabulk captures (John Doe subs): cards-02-add-card, portal-01-summary-active (replaces the wrong mockup flagged in 158909 :: docs: AutoPay public documentation #169), portal-02-trialing, portal-03-canceled-pending-reactivation, portal-04-expired (new — the Expired step had no image), portal-05-no-cards, recovery-01-past-due, states-03-magic-link-invalid.
  • Asset manifest under static/img/business/autopay/MANIFEST.md, which records for every asset whether it is a real capture or one of Menna's mockups, and why.

What is still a mockup (all listed in MANIFEST.md, none blocking this PR)

  • The three cancel/reactivate modal dialogs — the subs exist and portal-03 was captured from one, but the dialogs need an interactive click on the live portal, which was not viable here (CDP Page.captureScreenshot times out; the extension viewport caps at 360px). Capture via Menna or a follow-up session; the sub URLs are ready.
  • recovery-02-payment-confirmed — needs a completed payment (card entry).
  • states-01/02/04, notifications-01..06.
  • Consequently two clips still contain some mockup frames: retry-to-recovery (recovery-02) and notification-emails (notifications-01/03/05).

Copy alignment with Ankit's clip scripts (#158914 R5) is still worth a pass before these are treated as final.


Description corrected 2026-08-18 after @claude's review. The earlier body said the 5 clips were "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914)" and that a portal-01 recapture was pending. That was written before 38bf32a, which recaptured portal-01 and rebuilt every clip from the real screenshots, so the note described a state the branch had already moved past — and the TODO markers the review correctly could not find were never added because they had stopped being true. Adding them now would label real captures as provisional.

junaidsarfrazdevand others added 4 commits August 13, 2026 19:26
…, #158914)
Adds the video + screenshot assets on top of the AutoPay docs merged in #169.
#158914 — Remotion video pipeline:
- Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never
installed by npm ci nor walked by the site build. tsconfig excludes it; renders
run manually via `cd remotion && npm run render`.
- Reusable <VideoEmbed> component (poster-first, preload=none, reduced-motion safe).
- Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
- 5 first-cut clips embedded into the business page (setup, self-service, add-card,
retry-to-recovery, notifications).
#158913 — screenshots:
- cards-02-add-card.png captured from betabulk (John Doe), fills the add-card gap.
- Asset manifest under static/img/business/autopay/MANIFEST.md.
NOTE: the 5 clips are FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each
composition, the business page, and remotion/README.md. They must be revisited and
re-recorded once the betabulk AutoPay scenario URLs are available, with copy aligned
to Ankit's clip scripts (#158914 R5). portal-01 recapture (flagged in #169) also pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#158913, #158914)
Replaces mockups with real customer-portal captures (John Doe / betabulk) and
rebuilds the Remotion clips to sequence those real screenshots.
Screenshots (#158913) — 7 real betabulk captures now in the business-page sliders:
portal-01-summary-active (replaces the flagged wrong mockup), portal-02-trialing,
portal-03-canceled-pending-reactivation, portal-04-expired (new + wired into the
previously image-less Expired step), portal-05-no-cards, recovery-01-past-due,
states-03-magic-link-invalid. Kept as mockups (see MANIFEST.md): the three
cancel/reactivate dialogs, recovery-02, states-01/02/04, notifications-01..06.
Videos (#158914) — rebuilt from the real screenshots: new Reel component sequences
the real PNGs (staticFile from remotion/public/screens, copied by render-all.mjs,
gitignored) with captions + crossfades; all 5 clips re-rendered.
typecheck + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@junaidsarfrazdev
junaidsarfrazdev marked this pull request as ready for review August 18, 2026 13:51
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 44s —— View job


Claude finished the review

Todo list:

  • Gather context (PR diff, changed files, CLAUDE.md)
  • Review remotion/ workspace isolation (package.json, tsconfig, gitignore)
  • Review VideoEmbed component
  • Review AutoPay docs page changes
  • Review asset manifest / screenshots
  • Post final review

Summary

Solid, well-scoped PR. The remotion/ isolation is done carefully (own package.json/tsconfig/lockfile, remotion/node_modules|out|public gitignored, root tsconfig.json excludes it, README.md explicitly documents why npm ci/typecheck/build never touch it). VideoEmbed is a clean poster-first, click-to-play component (preload="none", respects prefers-reduced-motion, dark-mode aware CSS). The five compositions accurately match what's described in static/img/business/autopay/MANIFEST.md, and all referenced image/video paths in docs/business/autopay/index.md resolve to real committed files.

Finding

PR description says the placeholder flags are missing from the diff. The PR body states the 5 clips are "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each composition, the business page, and remotion/README.md." I grepped the full diff (compositions, Root.tsx, docs/business/autopay/index.md, remotion/README.md) for TODO(#158914), placeholder, and first-cut — none of these markers actually exist anywhere in the changed files. Right now a reader of docs/business/autopay/index.md or remotion/src/compositions/*.tsx has no signal that these 5 videos are provisional and pending re-recording against real betabulk scenario URLs + Ankit's clip scripts. Since this page ships to real merchants, worth either adding the flags as described or updating the PR description to match reality.

Fix this →

Minor / non-blocking

  • src/components/VideoEmbed/index.tsx:44-54 — when prefers-reduced-motion is set, clicking the poster swaps in the <video> with autoPlay={false}, so the user has to click twice (once on the custom poster button, once on the native play control) to actually start playback. Reasonable accessibility-first tradeoff, just noting the double-click UX.
  • Couldn't run npm run typecheck / npm run build myself — Bash execution required interactive approval in this environment that wasn't granted. Given the isolation approach is thoroughly documented and cross-checked in remotion/README.md (including "verified: a deliberate type error inside remotion/ does not fail the root typecheck"), I'd suggest CI confirm this rather than re-deriving it manually.
    · branch: task/158913-158914-autopay-assets

`autoPlay={!reduced}` meant a reader with `prefers-reduced-motion` clicked the
poster, got a paused `<video>`, and had to click the native control to actually
start it. That gate misreads the preference: it governs UNSOLICITED motion, and
`playing` only becomes true from the poster click, so playback here is always
user-initiated.
Autoplay is unconditional now, which makes `usePrefersReducedMotion` dead — the
hook existed for that one prop, so it goes with it.
Raised as a non-blocking note by @claude on PR #171.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Thanks — the finding was correct, but the fix is the other branch of what you offered.

The TODO(#158914) markers are genuinely absent, and should stay absent. They were never added because they stopped being true: 38bf32a (17 Aug) recaptured portal-01 and rebuilt all 5 clips from the real betabulk screenshots via the new Reel component. The PR body still carried the pre-rebuild note, so it described a state the branch had already moved past. Adding "first-cut placeholder" flags now would label real captures as provisional — the opposite of accurate.

The branch already documents this, which is worth checking against next time the two disagree:

  • static/img/business/autopay/MANIFEST.md § "Videos (#158914) — rebuilt from the REAL screenshots"
  • remotion/README.md, first line: "Clips are built from the REAL product screenshots."

So I've corrected the PR description instead, and it now also records what genuinely is still a mockup — the three cancel/reactivate modal dialogs (need an interactive click on the live portal), recovery-02, states-01/02/04, notifications-01..06 — and therefore that two clips still contain some mockup frames. That was the real gap: the honest caveat existed in MANIFEST.md but not in the PR.

Minor finding — fixed in 152610a. You were right that reduced-motion caused a double click. The gate also misread the preference: prefers-reduced-motion governs unsolicited motion, and playing only becomes true from the poster click, so playback there is always user-initiated. autoPlay is unconditional now, and usePrefersReducedMotion went with it since it existed for that one prop. npm run typecheck green.

On the third point — CI is the right place to confirm the remotion/ isolation, agreed. npm run typecheck passes locally after this change.

@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 28s —— View job


Claude finished re-reviewing @junaidsarfrazdev's PR

Todo list:

  • Gather context (PR diff, prior review discussion, CLAUDE.md)
  • Verify the 152610a fix (double-click / prefers-reduced-motion change) in VideoEmbed
  • Verify the PR description correction matches MANIFEST.md / README.md
  • Re-check remaining files (compositions, docs page, manifest) for anything new
  • Post final review

Summary

Both follow-ups from the previous review are handled correctly:

  • PR description: now accurately reflects that all 5 clips are rebuilt from real betabulk screenshots (not first-cut placeholders), and lists the genuine remaining mockups (3 modal dialogs, recovery-02, states-01/02/04, notifications-01..06). This matches static/img/business/autopay/MANIFEST.md and remotion/README.md, and docs/business/autopay/index.md's in-page comment was updated to match (git diff 9ca313e..HEAD -- docs/business/autopay/index.md) — the stale TODO(#158914) "FIRST-CUT PLACEHOLDERS" comment is gone, replaced with an accurate "built from the real betabulk screenshots" note.
  • 152610a: the fix itself is correct — playing only flips true from the poster's own click handler (src/components/VideoEmbed/index.tsx:51), so gating autoPlay on prefers-reduced-motion was never actually suppressing unsolicited motion, just adding a redundant second click. Making autoPlay unconditional and dropping the now-dead usePrefersReducedMotion hook is the right call, and the inline comment explains the non-obvious "why."

Finding

src/components/VideoEmbed/README.md:36-37 documents the behavior 152610a just removed. It still reads:

Reduced motion. When the OS requests reduced motion, the video does not autoplay after the click (autoPlay={!reduced}); the reader controls playback.

autoPlay={!reduced} and the reduced state no longer exist in index.tsxautoPlay is now unconditional. A future reader of this component's own README would be told about behavior that isn't there anymore, and would be citing dead code ({!reduced}) if they went looking for it.

Fix this →

Minor / non-blocking

  • docs/superpowers/plans/2026-08-12-autopay-assets-docs.md and docs/superpowers/specs/2026-08-12-autopay-assets-docs-design.md also mention usePrefersReducedMotion, but these are dated planning artifacts (design history), not live component docs — I wouldn't touch them.
  • Same limitation as the last review: couldn't run npm run typecheck myself (Bash execution needs interactive approval that wasn't granted here). You noted it's green locally after 152610a; I'd still lean on CI to confirm.

Everything else — the remotion/ isolation, the manifest's real-vs-mockup accounting, and the docs page's image/video paths — is unchanged since the last pass and still checks out.
· branch: task/158913-158914-autopay-assets

…emoved
It still documented `autoPlay={!reduced}` and a `reduced` state, neither of
which exists — so the component's own README sent a reader looking for deleted
code. Replaced with what the code does now, and why it is not a reduced-motion
violation: the `<video>` only mounts from the poster's click handler, so
playback is always user-initiated.
Caught by @claude on PR #171. I had grepped `index.tsx` for the hook when
removing it, but not the component's README beside it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Good catch — fixed in 70d02d0.

src/components/VideoEmbed/README.md still documented autoPlay={!reduced} and a reduced state, so the component's own README was pointing a reader at code deleted in 152610a. It now describes what the code does and why it isn't a reduced-motion violation: the <video> only mounts from the poster's click handler, so playback is always user-initiated.

My miss — when removing the hook I grepped index.tsx for it but not the README sitting beside it. I've swept the rest: no live reference to usePrefersReducedMotion or {!reduced} remains outside the dated planning artifacts.

Agreed on both minor points. The docs/superpowers/plans|specs files are design history from 2026-08-12 and should keep saying what was decided then — rewriting them would falsify the record. And npm run typecheck is green locally after both commits; CI is the right place to confirm that and the remotion/ isolation.

One thing worth recording since it isn't visible from the diff: I could not verify playback end-to-end in a browser. The clips don't decode in the Chrome available here — opening setup-subscription.mp4 directly, with no React involved, hangs at readyState 0 / videoWidth 0 with no error, though canPlayType('video/mp4; codecs="avc1.42E01E") reports probably. The files themselves are fine — valid faststart MP4 (moov before mdat), served 200 video/mp4, 540 KB — so this reads as a Linux Chromium build whose canPlayType over-reports while the proprietary H.264 decoder is absent, not a defect in the assets or the component. Someone should click through the five embeds on a normal browser before merge; the component behaviour either side of that is verified (poster-first, no <video> in the DOM until the click, then mounted with autoplay + muted and no second click needed).

@junaidsarfrazdev
junaidsarfrazdev merged commit 2aa9a7d into devAug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@junaidsarfrazdev
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); feat(autopay): Remotion video pipeline + add-card screenshot (#158913… by junaidsarfrazdev · Pull Request #171 · ottuco/docs · GitHub
Skip to content

feat(autopay): Remotion video pipeline + add-card screenshot (#158913… - #171

Merged
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets
Aug 18, 2026
Merged

feat(autopay): Remotion video pipeline + add-card screenshot (#158913…#171
junaidsarfrazdev merged 6 commits into
devfrom
task/158913-158914-autopay-assets

Conversation

@junaidsarfrazdev

@junaidsarfrazdevjunaidsarfrazdev commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds the video + screenshot assets on top of the AutoPay docs merged in #169.

#158914 — Remotion video pipeline

  • Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never installed by npm ci nor walked by the site build. tsconfig excludes it; renders run manually via cd remotion && npm run render.
  • Reusable <VideoEmbed> component (poster-first, preload=none, click-to-play).
  • Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
  • 5 clips embedded into the business page (setup, self-service, add-card, retry-to-recovery, notifications), sequenced from the real product screenshots via the Reel component — not synthetic mockups.

#158913 — screenshots

  • 8 real betabulk captures (John Doe subs): cards-02-add-card, portal-01-summary-active (replaces the wrong mockup flagged in 158909 :: docs: AutoPay public documentation #169), portal-02-trialing, portal-03-canceled-pending-reactivation, portal-04-expired (new — the Expired step had no image), portal-05-no-cards, recovery-01-past-due, states-03-magic-link-invalid.
  • Asset manifest under static/img/business/autopay/MANIFEST.md, which records for every asset whether it is a real capture or one of Menna's mockups, and why.

What is still a mockup (all listed in MANIFEST.md, none blocking this PR)

  • The three cancel/reactivate modal dialogs — the subs exist and portal-03 was captured from one, but the dialogs need an interactive click on the live portal, which was not viable here (CDP Page.captureScreenshot times out; the extension viewport caps at 360px). Capture via Menna or a follow-up session; the sub URLs are ready.
  • recovery-02-payment-confirmed — needs a completed payment (card entry).
  • states-01/02/04, notifications-01..06.
  • Consequently two clips still contain some mockup frames: retry-to-recovery (recovery-02) and notification-emails (notifications-01/03/05).

Copy alignment with Ankit's clip scripts (#158914 R5) is still worth a pass before these are treated as final.


Description corrected 2026-08-18 after @claude's review. The earlier body said the 5 clips were "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914)" and that a portal-01 recapture was pending. That was written before 38bf32a, which recaptured portal-01 and rebuilt every clip from the real screenshots, so the note described a state the branch had already moved past — and the TODO markers the review correctly could not find were never added because they had stopped being true. Adding them now would label real captures as provisional.

junaidsarfrazdevand others added 4 commits August 13, 2026 19:26
…, #158914)
Adds the video + screenshot assets on top of the AutoPay docs merged in #169.
#158914 — Remotion video pipeline:
- Isolated remotion/ workspace (own package.json/tsconfig/node_modules); never
installed by npm ci nor walked by the site build. tsconfig excludes it; renders
run manually via `cd remotion && npm run render`.
- Reusable <VideoEmbed> component (poster-first, preload=none, reduced-motion safe).
- Hosting decision: small compressed H.264 MP4s committed to static/video/autopay/.
- 5 first-cut clips embedded into the business page (setup, self-service, add-card,
retry-to-recovery, notifications).
#158913 — screenshots:
- cards-02-add-card.png captured from betabulk (John Doe), fills the add-card gap.
- Asset manifest under static/img/business/autopay/MANIFEST.md.
NOTE: the 5 clips are FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each
composition, the business page, and remotion/README.md. They must be revisited and
re-recorded once the betabulk AutoPay scenario URLs are available, with copy aligned
to Ankit's clip scripts (#158914 R5). portal-01 recapture (flagged in #169) also pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…#158913, #158914)
Replaces mockups with real customer-portal captures (John Doe / betabulk) and
rebuilds the Remotion clips to sequence those real screenshots.
Screenshots (#158913) — 7 real betabulk captures now in the business-page sliders:
portal-01-summary-active (replaces the flagged wrong mockup), portal-02-trialing,
portal-03-canceled-pending-reactivation, portal-04-expired (new + wired into the
previously image-less Expired step), portal-05-no-cards, recovery-01-past-due,
states-03-magic-link-invalid. Kept as mockups (see MANIFEST.md): the three
cancel/reactivate dialogs, recovery-02, states-01/02/04, notifications-01..06.
Videos (#158914) — rebuilt from the real screenshots: new Reel component sequences
the real PNGs (staticFile from remotion/public/screens, copied by render-all.mjs,
gitignored) with captions + crossfades; all 5 clips re-rendered.
typecheck + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@junaidsarfrazdev
junaidsarfrazdev marked this pull request as ready for review August 18, 2026 13:51
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 44s —— View job


Claude finished the review

Todo list:

  • Gather context (PR diff, changed files, CLAUDE.md)
  • Review remotion/ workspace isolation (package.json, tsconfig, gitignore)
  • Review VideoEmbed component
  • Review AutoPay docs page changes
  • Review asset manifest / screenshots
  • Post final review

Summary

Solid, well-scoped PR. The remotion/ isolation is done carefully (own package.json/tsconfig/lockfile, remotion/node_modules|out|public gitignored, root tsconfig.json excludes it, README.md explicitly documents why npm ci/typecheck/build never touch it). VideoEmbed is a clean poster-first, click-to-play component (preload="none", respects prefers-reduced-motion, dark-mode aware CSS). The five compositions accurately match what's described in static/img/business/autopay/MANIFEST.md, and all referenced image/video paths in docs/business/autopay/index.md resolve to real committed files.

Finding

PR description says the placeholder flags are missing from the diff. The PR body states the 5 clips are "FIRST-CUT PLACEHOLDERS — flagged with TODO(#158914) in each composition, the business page, and remotion/README.md." I grepped the full diff (compositions, Root.tsx, docs/business/autopay/index.md, remotion/README.md) for TODO(#158914), placeholder, and first-cut — none of these markers actually exist anywhere in the changed files. Right now a reader of docs/business/autopay/index.md or remotion/src/compositions/*.tsx has no signal that these 5 videos are provisional and pending re-recording against real betabulk scenario URLs + Ankit's clip scripts. Since this page ships to real merchants, worth either adding the flags as described or updating the PR description to match reality.

Fix this →

Minor / non-blocking

  • src/components/VideoEmbed/index.tsx:44-54 — when prefers-reduced-motion is set, clicking the poster swaps in the <video> with autoPlay={false}, so the user has to click twice (once on the custom poster button, once on the native play control) to actually start playback. Reasonable accessibility-first tradeoff, just noting the double-click UX.
  • Couldn't run npm run typecheck / npm run build myself — Bash execution required interactive approval in this environment that wasn't granted. Given the isolation approach is thoroughly documented and cross-checked in remotion/README.md (including "verified: a deliberate type error inside remotion/ does not fail the root typecheck"), I'd suggest CI confirm this rather than re-deriving it manually.
    · branch: task/158913-158914-autopay-assets

`autoPlay={!reduced}` meant a reader with `prefers-reduced-motion` clicked the
poster, got a paused `<video>`, and had to click the native control to actually
start it. That gate misreads the preference: it governs UNSOLICITED motion, and
`playing` only becomes true from the poster click, so playback here is always
user-initiated.
Autoplay is unconditional now, which makes `usePrefersReducedMotion` dead — the
hook existed for that one prop, so it goes with it.
Raised as a non-blocking note by @claude on PR #171.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Thanks — the finding was correct, but the fix is the other branch of what you offered.

The TODO(#158914) markers are genuinely absent, and should stay absent. They were never added because they stopped being true: 38bf32a (17 Aug) recaptured portal-01 and rebuilt all 5 clips from the real betabulk screenshots via the new Reel component. The PR body still carried the pre-rebuild note, so it described a state the branch had already moved past. Adding "first-cut placeholder" flags now would label real captures as provisional — the opposite of accurate.

The branch already documents this, which is worth checking against next time the two disagree:

  • static/img/business/autopay/MANIFEST.md § "Videos (#158914) — rebuilt from the REAL screenshots"
  • remotion/README.md, first line: "Clips are built from the REAL product screenshots."

So I've corrected the PR description instead, and it now also records what genuinely is still a mockup — the three cancel/reactivate modal dialogs (need an interactive click on the live portal), recovery-02, states-01/02/04, notifications-01..06 — and therefore that two clips still contain some mockup frames. That was the real gap: the honest caveat existed in MANIFEST.md but not in the PR.

Minor finding — fixed in 152610a. You were right that reduced-motion caused a double click. The gate also misread the preference: prefers-reduced-motion governs unsolicited motion, and playing only becomes true from the poster click, so playback there is always user-initiated. autoPlay is unconditional now, and usePrefersReducedMotion went with it since it existed for that one prop. npm run typecheck green.

On the third point — CI is the right place to confirm the remotion/ isolation, agreed. npm run typecheck passes locally after this change.

@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

@claude review

@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown

Claude finished @junaidsarfrazdev's task in 1m 28s —— View job


Claude finished re-reviewing @junaidsarfrazdev's PR

Todo list:

  • Gather context (PR diff, prior review discussion, CLAUDE.md)
  • Verify the 152610a fix (double-click / prefers-reduced-motion change) in VideoEmbed
  • Verify the PR description correction matches MANIFEST.md / README.md
  • Re-check remaining files (compositions, docs page, manifest) for anything new
  • Post final review

Summary

Both follow-ups from the previous review are handled correctly:

  • PR description: now accurately reflects that all 5 clips are rebuilt from real betabulk screenshots (not first-cut placeholders), and lists the genuine remaining mockups (3 modal dialogs, recovery-02, states-01/02/04, notifications-01..06). This matches static/img/business/autopay/MANIFEST.md and remotion/README.md, and docs/business/autopay/index.md's in-page comment was updated to match (git diff 9ca313e..HEAD -- docs/business/autopay/index.md) — the stale TODO(#158914) "FIRST-CUT PLACEHOLDERS" comment is gone, replaced with an accurate "built from the real betabulk screenshots" note.
  • 152610a: the fix itself is correct — playing only flips true from the poster's own click handler (src/components/VideoEmbed/index.tsx:51), so gating autoPlay on prefers-reduced-motion was never actually suppressing unsolicited motion, just adding a redundant second click. Making autoPlay unconditional and dropping the now-dead usePrefersReducedMotion hook is the right call, and the inline comment explains the non-obvious "why."

Finding

src/components/VideoEmbed/README.md:36-37 documents the behavior 152610a just removed. It still reads:

Reduced motion. When the OS requests reduced motion, the video does not autoplay after the click (autoPlay={!reduced}); the reader controls playback.

autoPlay={!reduced} and the reduced state no longer exist in index.tsxautoPlay is now unconditional. A future reader of this component's own README would be told about behavior that isn't there anymore, and would be citing dead code ({!reduced}) if they went looking for it.

Fix this →

Minor / non-blocking

  • docs/superpowers/plans/2026-08-12-autopay-assets-docs.md and docs/superpowers/specs/2026-08-12-autopay-assets-docs-design.md also mention usePrefersReducedMotion, but these are dated planning artifacts (design history), not live component docs — I wouldn't touch them.
  • Same limitation as the last review: couldn't run npm run typecheck myself (Bash execution needs interactive approval that wasn't granted here). You noted it's green locally after 152610a; I'd still lean on CI to confirm.

Everything else — the remotion/ isolation, the manifest's real-vs-mockup accounting, and the docs page's image/video paths — is unchanged since the last pass and still checks out.
· branch: task/158913-158914-autopay-assets

…emoved
It still documented `autoPlay={!reduced}` and a `reduced` state, neither of
which exists — so the component's own README sent a reader looking for deleted
code. Replaced with what the code does now, and why it is not a reduced-motion
violation: the `<video>` only mounts from the poster's click handler, so
playback is always user-initiated.
Caught by @claude on PR #171. I had grepped `index.tsx` for the hook when
removing it, but not the component's README beside it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@junaidsarfrazdev

Copy link
Copy Markdown
ContributorAuthor

Good catch — fixed in 70d02d0.

src/components/VideoEmbed/README.md still documented autoPlay={!reduced} and a reduced state, so the component's own README was pointing a reader at code deleted in 152610a. It now describes what the code does and why it isn't a reduced-motion violation: the <video> only mounts from the poster's click handler, so playback is always user-initiated.

My miss — when removing the hook I grepped index.tsx for it but not the README sitting beside it. I've swept the rest: no live reference to usePrefersReducedMotion or {!reduced} remains outside the dated planning artifacts.

Agreed on both minor points. The docs/superpowers/plans|specs files are design history from 2026-08-12 and should keep saying what was decided then — rewriting them would falsify the record. And npm run typecheck is green locally after both commits; CI is the right place to confirm that and the remotion/ isolation.

One thing worth recording since it isn't visible from the diff: I could not verify playback end-to-end in a browser. The clips don't decode in the Chrome available here — opening setup-subscription.mp4 directly, with no React involved, hangs at readyState 0 / videoWidth 0 with no error, though canPlayType('video/mp4; codecs="avc1.42E01E") reports probably. The files themselves are fine — valid faststart MP4 (moov before mdat), served 200 video/mp4, 540 KB — so this reads as a Linux Chromium build whose canPlayType over-reports while the proprietary H.264 decoder is absent, not a defect in the assets or the component. Someone should click through the five embeds on a normal browser before merge; the component behaviour either side of that is verified (poster-first, no <video> in the DOM until the click, then mounted with autoplay + muted and no second click needed).

@junaidsarfrazdev
junaidsarfrazdev merged commit 2aa9a7d into devAug 18, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@junaidsarfrazdev