Repository navigation
feat(registry): add five vertical ad-template blocks and their motion primitives - #3217
Conversation
… component A vertical ad-template block: phone notifications land one after another on a 2.000s beat and stack up the screen, each banner pushing the pile down as it arrives, before the whole stack lifts away into a closing card carrying the HyperFrames lockup. Every decisive number - the 214px pitch, the 22px entry rise, the expo.out restack - is measured from reference footage rather than invented. The backdrop plate is a generated photograph, shipped with the item. The banner-push-in component carries the reusable arrival move on its own: one banner fades in and rises into place while everything already on screen slides up one pitch in lockstep. Both pass the full browser gate (runtime, layout, motion, WCAG AA contrast) installed into a scratch project from a served registry.
…p component A share sheet springs up from the bottom of the phone and cycles photographic previews inside its card on a fast cut rhythm - fourteen cuts over 7.2s - while the blurred ground swaps behind it on the same beats, ending on an accept tap. A brand strip with the HyperFrames lockup rides the bottom of the preview, as the reference's did. The four stills are generated photographs, shipped with the item. The sheet-spring-up component carries the arrival on its own: a real spring sampled frame by frame from reference footage - up from below, 192px overshoot, 0.72s settle - shipped as the sampled table rather than an ease that approximates it. Both pass the full browser gate (WCAG AA) installed from a served registry.
Two chat primitives extracted from reference footage of real conversations. typing-indicator is the three-dot bubble that says someone is writing: it pops in at the thread's edge on the measured entry (scale 0.6 to 1, alpha 0.4 to 1, 0.10s power2.out), holds, and vanishes when the message lands. An optional bounded dot wave is included for compositions that want the dots to breathe. streaming-text is not a typewriter: words arrive in the uneven bursts of a streamed AI answer, on a token rhythm measured word-by-word from the reference, each word landing grey and inking to full colour over 0.27s. The GAPS table ships in the integration note and cycles for any word count. Both demos pass the browser gate.
A question is typed on a rising keyboard - measured keystroke rhythm, steady caret - sent, and answered by an AI that streams its reply word by word: thinking dot on the measured alpha ramp, tokens arriving in uneven bursts, a bulleted list, then a cut to a branded closing card. The typing and streaming schedules are generated at load from the measured gap tables, so every piece of copy is a variable - question, three answer paragraphs, three bullets, and the whole closing card - while the rhythm stays the reference's. Kept at the native 750x1624 capture size so the measured keyboard geometry stays pixel-true. Passes the full browser gate (145/145 WCAG AA) installed from a served registry.
A full text conversation plays out on a phone: bubbles popping in on their measured entries, typing indicators holding the beat, a shared link card, an emoji burst, delivered receipts, the composer typing five messages keystroke by keystroke - and the whole thread scrolling up beat by beat on the measured y-choreography until a warm closing card lands. Every message swap keeps the measured keystroke tables intact: the new copy is length-matched character for character to the reference's typed lines, so all 97 typed frames land on their original beats. The footage plate is replaced by a CSS room-and-phone-body, the link card carries a generated still, and the closing card is rebuilt around the HyperFrames lockup with its stars, proof line, and feature icons preserved. Relates to the thread-message-stack work in #3046: that PR ships a caller-payload message-stack component; this block is the complete ad-template film around the same subject. Kept as its own commit so either can move independently. Passes the full browser gate (65/65 WCAG AA) installed from a served registry.
…nent A personal note is typed character by character in a notes app - the caret riding every letter on the measured keystroke frames, the page scrolling up on the measured settle curves as each line lands - then cuts to a paper card with a marker headline, a circled word, a ticked checklist, and the video card. New copy is length-matched line by line to the measured reveal table, so all 176 keystrokes land on their original frames. The two hand-drawn faces (Permanent Marker, Courier Prime - both OFL) ship with the item; the reference's proprietary UI face is replaced by the system stack. The line-reveal-list component carries the paragraph rhythm on its own: lines land on the measured writing cadence that slows as the thought gets heavier - 2.20s, 2.03s, 2.97s, 3.10s, 3.33s, 3.63s - and the page makes room with the measured scroll-settle table instead of a linear glide. Both pass the browser gate (366/366 WCAG AA for the block) installed from a served registry.
Regenerated pages, payloads, navigation and the flat index for the five blocks and five components added in the preceding commits. Every existing page is untouched: the diff is ten new item pages, their payload assets, and the two regenerated indexes.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
The repo-wide format gate covers registry HTML; the staged-file hook did not reach these. Payloads and pages regenerated to match.
The first demos dropped each primitive onto a bare canvas, which stripped the context the moves were measured in - a dark bubble on a black frame, a sheet floating in empty gradient. Each demo now plays inside a phone on a studio ground, in the move's native habitat - lock screen, chat thread, share sheet, assistant answer, notes page - with a specimen caption naming the component and its measured numbers. Interiors are authored at 1080x1920 and scaled into the screen, so they reuse the blocks' gate-proven geometry. Timelines are unchanged. All five pass the browser gate.
The video-primitive tag pins an item to the Motion Primitives shelf and overrides every other grouping rule - right for an atomic move, wrong for a 25-second film. The five ad-template blocks move to the Showcases shelf (Scenes & demos), where complete scenes live; the primitives shelf keeps only the moves.
Reviewed against the shelf they would join and cut as duplicates. banner-push-in was the thinnest cut against the existing notification family - notification-stack already owns the arrival-plus-lockstep-shift move, mirrored. line-reveal-list was pinched from both sides: the existing line-by-line-slide owns generic staggered lines, and the incoming notes-typing scene carries the measured writing cadence and scroll-settle at scene level. Their measured tables live on inside the films they were extracted from.
social-proof-card: the app-store close as one scene - wordmark, five stars, proof line, three feature icons, CTA capsule - in a quiet stagger. Composes with, not against, star-rating-fill / testimonial-proof-card / cta-lockup, which stay the atomic owners of their moves. marker-checklist-card: a hand-lettered paper card - marker headline, an ellipse that draws itself around one word, checklist rows whose checks draw on. The paper-and-marker sibling of mk-specs-list. chat-thread: a conversation as a scene - measured bubble pop-ins, expo lockstep shifts, typing dots holding the beat, a media placeholder. Message content is one variable: heights are measured at mount and the choreography is generated to fit. Relates to #3046's caller-payload stack; kept independent. notes-typing: the notes-app confession - lines typed on the measured human keystroke rhythm, the caret riding every landed character. The scene counterpart to typed-prompt's bare prompt line. All four follow notification-stack's mountable-scene pattern: container units, theme-contract tokens, one paused timeline registered under the literal id. All demos pass the browser gate.
Ten pages become twelve: the five films move to the Showcases shelf, the two retired components' pages are gone, and the four scene primitives get pages under Motion Scenes. Every untouched page is byte-identical.
…e type switch The scene now carries everything the reference conversation carries: status bar, back badge, avatar and name pill, bubbles with real iMessage tails, a Delivered receipt under the last sent bubble, large emoji rows, a media placeholder, and a link card with title, domain and chevron. Every message picks its type by prefix, the way marker-highlight picks a style: recv:/sent: text bubbles, emoji: a large row, img a media placeholder, card:Title~domain a link card. Heights are still measured at mount and the choreography generated, so any mix of types fits.
ONE message arrives on the measured entry, growing from its sender's corner. The type is a proper enum - Received, Sent, Emoji, Image, Link card - switched on the catalog page the way marker-highlight switches its style, with the bubble tail and the Delivered receipt as their own switches. chat-thread remains the conversation-as-scene built from arrivals like this one; the pipe grammar belongs at that level, the enum belongs here. Demo cycles all five types, one at a time, with a type chip naming each.
jrusso1020
left a comment
There was a problem hiding this comment.
Reviewed at head c5fafdbdde67ba747ac51ccb818b017490f23c28. First review on the PR — no prior reviews or inline comments to be additive against.
Audited end-to-end: all 21 authored HTML files (5 films, 8 component sources, 8 demos), all 13 registry-item.json, the registry/registry.json hunk, scripts/generate-catalog-pages.ts shelf routing (on main, to check where these land).
Trusting: the 13 generated docs/public/catalog/** payloads, catalog-index.json, local-vectors.{bin,json} and the hashed asset copies — spot-verified by blob SHA rather than read (see below), plus docs/catalog/*.mdx, which are generated from the sources I did read.
This is unusually careful work, and the measured numbers are real — I checked the falsifiable ones rather than taking the table's word:
sheet-spring-up.html:228-237— the SPRING table is 22 steps, peak-192at0.423s, settles to0at0.723s. Matches "22-step y/alpha table · 192px overshoot · 0.72s settle" exactly.streaming-text.html:244-248— GAPS is 29 entries, and the ink ramp isduration: 0.2667. Matches "29-gap token rhythm · 0.27s ramp".- All five film durations and dimensions match the Tier 1 table, including the deliberate
750x1624onai-chat-reveal. - Net catalog additions are exactly 13: 15 added minus
banner-push-inandline-reveal-listremoved in the same diff. The "considered and cut" section is verifiable in the patch, which is rare and worth saying. - All 15 mirrored assets under
docs/public/catalog/items/**are byte-identical to theirregistry/**sources (compared by git blob SHA, not by name).
Shelf routing verified at source, because it reads inverted at a glance. Anyone eyeballing the tags will think Tier 2 and Tier 3 are swapped. They are not — generate-catalog-pages.ts:1190 maps video-primitive → Motion Primitives as a first-priority declared membership, and :1230 maps motion-primitive → Motion Scenes. I traced all 13 through groupForItem and every one lands where the PR body says: films on Showcases via :1208, the four scene primitives on Motion Scenes, the four motion primitives on Motion Primitives. No change needed; flagging only so the next reader doesn't "fix" it.
blocker — iMessage ships as rendered on-screen copy
The PR body says "Fully de-branded" and "all brand copy was replaced." Two shipped compositions render the literal string as visible pixels:
registry/components/chat-thread/chat-thread.html:425—<div class="cht-ph">iMessage</div>registry/blocks/message-thread-reveal/message-thread-reveal.html:724—<div id="mtr-ph">iMessage</div>
It is deliberately on screen, not incidental: message-thread-reveal.html toggles #mtr-ph visible and back ten times across the film (:1221, :1224, :1249, :1252, :1303, :1306, :1327, :1330, :1389, :1392), so it is in frame for most of the composer's life. It also propagates into the published catalog pages — docs/catalog/components/chat-thread.mdx:1150, docs/catalog/blocks/message-thread-reveal.mdx:740 and :2253.
To be clear about what I am not flagging: the CSS and JS comments that reference iMessage as technique provenance (chat-thread.html:175, :572, message-thread-reveal.html:196) are fine — that is describing where a measurement came from. The composer placeholder is different in kind, because it is third-party trademarked copy rendering inside a template that this repo publishes for people to install and put in ads.
chat-thread already exposes contact as a variable, so a user who swaps every string the schema offers them still ships this one. Fix is one line each — either a placeholder variable defaulting to Message, or just the generic string.
nit — the OFL claim is imprecise
Provenance says "faces are OFL." Courier Prime is OFL 1.1, but Permanent Marker is distributed under Apache-2.0 on Google Fonts, not OFL. Worth rewording to name both licences. I could not verify the embedded licence record inside the .woff2 binaries, so please confirm rather than take my word.
Explicitly not a finding against this PR: no font licence files ship alongside the fonts. main already carries 13 .woff2 under registry/ with no per-font licence, so that is a repo-wide convention question, not yours to fix here.
nit — social-proof-card's tag is one word from moving shelf
It carries social-proof, and generate-catalog-pages.ts:1201 routes anything tagged social to Social Overlays — several checks earlier than the motion-primitive rule that puts this item on Motion Scenes. Exact-match on the array element saves it today. If someone later adds social as a sibling tag it silently leaves the shelf this PR put it on, with green CI. Not worth changing now; worth knowing.
note — what the green gate does and does not cover
126 data-layout-allow-* markers land in this PR, concentrated in message-thread-reveal.html (43) and notes-reveal.html (36). In the first, they are systematic rather than ad hoc — three markers on each of the fourteen .item rows plus one wrapper — which is defensible for absolutely-positioned bubbles whose tails and pop-in deliberately cross their own box.
The thing worth stating plainly: those markers are what make the layout portion of check pass on those files, so on the chat surfaces the collision gate is off by construction. The body's "629/629 WCAG AA text checks" is a contrast result and says nothing about layout, so the two should not be read as one validation story. I am not asking for a change — the reference genuinely layers content here, which is exactly the carve-out the markers exist for. I mention it because a reader sees "629/629" and infers more coverage than was actually measured.
CI at this head
Zero failures and zero cancelled runs, collapsed to the latest run per check name. The required set for main is satisfied: Semantic PR title and regression succeeded, and the other six required contexts are skipped, which satisfies them. The two gates with real signal for a catalog PR — Catalog: search index covers the registry and Render catalog previews — both passed, as did Validate docs and preview-regression. BLOCKED here is the reviewer gate alone, not CI.
Verdict: REQUEST CHANGES
Reasoning: Everything measurable in the PR body checks out against the diff, and the catalog wiring is correct where it looks wrong — but a third-party trademark renders on screen in two shipped templates while the body states the work is fully de-branded, and that is cheap to fix now and awkward once installed downstream. Re-stamp as soon as the placeholder is a variable or a generic string; nothing else here is blocking.
— Rames Jusso
miga-heygen
left a comment
There was a problem hiding this comment.
Thirteen catalog items across three tiers (5 blocks, 4 scene primitives, 4 motion primitives). Thorough spot-check across compositions, catalog index, docs nav, and assets.
All framework invariants hold:
- Deterministic rendering: no
Date.now(), no unseededMath.random(), no runtimefetch() - Clip structure:
class="clip"with properdata-start,data-duration,data-track-index - GSAP timelines:
paused: true, registered onwindow.__timelines[compositionId] - Variables: declared via
data-composition-variableswith correct schema - Security:
innerHTMLonly on hardcoded HTML strings, never user input. Variable text usestextContent/createTextNode. Noeval, no external script sources - Asset integrity: all referenced fonts and images verified present at declared paths
- Catalog integrity: 1:1 correspondence across
catalog-index.json,docs.json,.mdxfiles, andregistry-item.json. No orphans, no dangling references - Duration consistency:
data-composition-durationmatchesdata-durationon root; clip sums verified
No blocking issues. Two easy fixes worth doing before merge:
1. Tag typo: remocn-port across 31 registry-item.json files. Should be remotion-port. New to this PR (0 occurrences on main). Quick sed fix + regenerate catalog-index.json.
2. GSAP version: notes-reveal loads [email protected] while every other new file uses [email protected]. Should be aligned.
Non-blocking observations:
chat-messageis taggedvideo-primitivewith file typehyperframes:snippet, but its HTML structure (template wrapper,data-composition-id, paused timeline onwindow.__timelines) matches the mountable-scene pattern. Won't break rendering, but someone using it as a paste-in snippet would get inert template content. Consider re-tagging asmotion-primitiveor restructuring.- Tag vocabulary drift:
effect(15) vseffects(8),text-effect(5) vstext-effects(6), etc. Pre-existing, amplified by volume. - Sub-frame timing drift:
ai-chat-revealend-card clip starts at15.8but timeline animates at15.8333(1 frame gap at 30fps). Not visible.
LGTM — ship it after the typo and GSAP version fixes.
Review by Miga
|
Additive to Miga's review — I verified both of its items against the artifact rather than inheriting them, and they come out differently. The The Two reasons it should not be a merge precondition here beyond that:
Net: one real fix on this PR ( — Rames Jusso |
…ont licences Review fixes for #3217: - Rendered composer placeholder "iMessage" -> "Message" in chat-thread, its demo, and message-thread-reveal (technique comments stay as provenance) - notes-reveal now loads [email protected] like every other item - Licence wording names each face: Courier Prime OFL 1.1, Permanent Marker Apache-2.0 (verified against embedded name-table records) Mirrored catalog payloads and pages regenerated for the four touched items.
|
Fixed at 291e208 — mirrored payloads/pages regenerated for the four touched items, browser gate re-run on the two remounted blocks (0 errors, 216/216 contrast).
@miga-heygen: gsap pinned to 3.14.2 in |
miguel-heygen
left a comment
There was a problem hiding this comment.
Exact-head follow-up at 291e2088252e9ecce5b646cc8fcf673ddbb5f5a8, additive to Rames Jusso's substantive review at the prior head.
Audited: the complete 14-file delta from c5fafdbd to this head; authored chat-thread source/demo and message-thread-reveal source; notes-reveal source; all touched MDX/public JSON mirrors; embedded WOFF2 name-table license records; exact-head required checks and current review state.
Trusting: the untouched portion of this 105-file / ~28k-LoC PR. Rames audited all 21 authored HTML files and 13 registry manifests end-to-end at the prior head; Miga independently spot-checked framework/catalog invariants. I did not re-read the unchanged generated payloads, binary assets, or remaining compositions.
The blocking rendered-copy issue is fixed at every affected authored surface: registry/components/chat-thread/chat-thread.html:425, its demo at :509, and registry/blocks/message-thread-reveal/message-thread-reveal.html:724 now render the generic Message; the touched catalog mirrors match. Remaining iMessage mentions are technique/provenance descriptions, which the prior review explicitly excluded from the blocker. registry/blocks/notes-reveal/notes-reveal.html:1040 and both generated MDX copies now use GSAP 3.14.2. The additional license wording is accurate against the embedded font records: Permanent Marker points to Apache-2.0 and Courier Prime to OFL.
The required exact-head set is terminal: Semantic PR title and regression passed; the six non-applicable required contexts are skipped. No required context is pending or failing.
Verdict: APPROVE
Reasoning: The sole blocker and the GSAP consistency issue are fixed across authored and generated surfaces at the exact current head, the additive license correction is accurate, and every required exact-head check is terminal-success/skipped.
— Magi
miga-heygen
left a comment
There was a problem hiding this comment.
Fixes confirmed:
- GSAP version aligned to
3.14.2acrossnotes-reveal,chat-thread, andmarker-checklist-card(4 files) - De-branding:
iMessage→Messageinmessage-thread-reveal - Neutral composer placeholder in
marker-checklist-card
Both flagged items from the first round are resolved. LGTM — ship it.
Review by Miga
jrusso1020
left a comment
There was a problem hiding this comment.
Re-reviewed at head 291e2088252e9ecce5b646cc8fcf673ddbb5f5a8. My prior CHANGES_REQUESTED was at c5fafdbdde and this repo does not dismiss on push, so it stayed live and gating — replacing it now that I have verified the fix rather than taking the fix commit's word for it.
The fix commit is exactly 1 ahead, 14 files, all one- and three-line hunks. I diffed c5fafdbdde...291e2088 directly instead of assuming a clean rebase, so this is a review of what actually changed.
The blocker is fixed
iMessage no longer renders as on-screen copy anywhere in the PR:
chat-thread.html:425andmessage-thread-reveal.html:724both now readMessage.- The mirrored artifacts moved with them —
docs/catalog/**pages and the escaped-HTMLdocs/public/catalog/**payload blobs all carrycht-ph">Message</mtr-ph">Message<. That is the part most likely to be missed on a de-branding fix, since the generated payloads embed the whole document as one string, and it is in sync here. - Zero rendered text nodes matching
>…iMessage…<remain across the whole diff.
The 25 surviving iMessage mentions are all in the category I explicitly said was fine in the first pass: CSS/JS technique comments (/* iMessage tails … */), the receipt variable's schema description, and catalog prose describing where a measurement came from. Describing provenance is not the same as shipping the trademark into someone's ad, and I don't want the earlier blocker read as a reason to scrub those.
Both follow-ups landed
- GSAP is now uniform. All 51
gsap@occurrences in the diff are3.14.2; zero3.12.5left. Credit to @miga-heygen fornotes-reveal.html:1040— I had checked whether the jsdelivr tag was house style and never diffed the versions across the tags, so that one was mine to miss. - The licence wording is now correct, and in more places than I flagged. I only asked about the provenance line; this also fixes the rendered claim in
marker-checklist-card/demo.html:341("OFL faces" → "Open faces — Permanent Marker (Apache-2.0) + Courier Prime (OFL 1.1)"). Naming both licences explicitly is the right call, and catching the visible stat block as well as the comment is the more complete fix.
CI at this exact head
Collapsed to the latest run per check name: zero failures, zero cancelled, nothing pending. All eight required contexts are satisfied — Semantic PR title and regression succeeded, the other six are skipped. The gates that carry real signal for a catalog change also passed: Catalog: search index covers the registry, Render catalog previews, Validate docs, preview-regression, and the three CodeQL analyses.
One scope note, not an objection: the re-run browser gate cited in the fix commit is 216 contrast checks against the two remounted blocks, not the 629 from the original full-catalog pass. That is the right scope for a 14-file text change, and the full-catalog gates above ran green at this head regardless.
Nothing from my first review is outstanding. The data-layout-allow-* observation stands as a note for future readers rather than a request — the markers are systematic and the layered chat bubbles are exactly the carve-out they exist for.
Verdict: APPROVE
Reasoning: Both fixes verified at source at the exact head, the generated artifacts are in sync with their sources, and every required check is terminal-satisfied. Leaving the merge itself to a maintainer.
— Rames Jusso
What
Five vertical ad-template films, four scene primitives extracted from their moments, and four motion primitives extracted from their moves — thirteen catalog items in three deliberate tiers, every decisive number measured frame-by-frame from reference footage of real high-performing vertical ads. Fully de-branded: generated photography, this repo's own lockups, open-licensed faces (OFL 1.1 / Apache-2.0), all copy as variables.
Tier 1 — films (blocks, Showcases shelf)
notification-cascadeshare-sheet-carouselai-chat-revealmessage-thread-revealnotes-revealTier 2 — scene primitives (components, Motion Scenes shelf)
Mountable scenes in the
notification-stackpattern: container units, theme-contract tokens, one paused timeline under the literal id, content as variables.social-proof-cardstar-rating-fill/testimonial-proof-card/cta-lockup— those stay the atomic ownersmarker-checklist-cardmk-specs-list's clean rowschat-threadrecv:/sent:/emoji:/img/card:Title~domain— and heights are measured at mount so any thread fitsnotes-typingtyped-prompt's bare prompt lineTier 3 — motion primitives (components, Motion Primitives shelf)
chat-messagechat-threadbuilds conversations fromsheet-spring-uptyping-indicatorstreaming-textConsidered and cut, so review can be fast
banner-push-in— retired in-PR:notification-stackalready owns arrival-plus-lockstep-shift, mirrored.line-reveal-list— retired in-PR: pinched betweenline-by-line-slide(generic staggered lines) andnotes-typing(the cadence at scene level).notes-typingtyping-effect — folded into the scene instead;typed-promptowns the bare line.video-primitiveand landed on the Motion Primitives shelf; reshelved to Showcases where complete scenes live.Previews
Catalog pages, payloads, navigation, flat index and the on-device search index are regenerated in-PR (the embedding model was fetched locally, so the maintainer regeneration step is already done).
Validation
Every film was installed through the real flow — registry served over HTTP,
hyperframes addinto a cleaninitproject — and passed thehyperframes checkbrowser gate there (629/629 WCAG AA text checks across the five). Every component demo passes the same gate; demos stage each primitive in its native habitat on a device, with its measured numbers beside it.data-layout-allow-*markers are used only where the reference itself layers content.Provenance
Rebuilt from reference footage of five widely-run vertical ad templates, reverse-engineered to per-frame specs (entry curves, cut rhythms, keystroke and token tables, scroll-settle curves), then re-authored as original HyperFrames compositions. No reference assets ship: photography is generated, logos are this repo's own, faces are open-licensed (Courier Prime under OFL 1.1, Permanent Marker under Apache-2.0 — verified against each woff2's embedded name-table licence records), and all brand copy was replaced.