feat(catalog): play the real composition on catalog pages - #3168
Merged
Conversation
Catalog previews were uploaded MP4s, published by hand to the CDN. Each page now embeds the composition itself, running in <hyperframes-player>, so a preview is the block rather than a recording of it. The composition is delivered as JSON under docs/public/catalog, and the player is mounted inside an iframe. Both are forced: the docs host publishes only JSON and images out of docs/public, and its MDX renderer strips unknown custom elements, so a player written into the page never reaches the DOM and an .html payload 404s in production. Assets are inlined as data URIs, which sidesteps the file-type restriction for fonts, scripts and models alike. 164 of 168 items build a payload; the rest keep their MP4 and say so.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
Fallow audit reportFound 15 findings. Duplication (4)
Health (11)
Generated by fallow. |
3 tasks
Fonts were being base64'd into every payload that used them, so a handful of files cost tens of megabytes in the repository to say the same thing over and over. Assets are now written once, content-addressed, under docs/public/catalog/assets and linked. Which types can be hosted was settled by fetching one file of each from a deployed preview: woff2, wav, mp4, svg and the image formats are published, glb is not. Types the host drops still travel inside the payload, because a link that 404s is worse than a larger payload. Also fixes the four type errors the scripts typecheck caught, all of them unchecked index access on a split() result.
| continue; | ||
| } | ||
|
|
||
| const bytes = readFileSync(source); |
| const dest = join(target.dir, name); | ||
| if (!existsSync(dest)) { | ||
| mkdirSync(target.dir, { recursive: true }); | ||
| writeFileSync(dest, bytes); |
| const dest = join(target.dir, name); | ||
| if (!existsSync(dest)) { | ||
| mkdirSync(target.dir, { recursive: true }); | ||
| writeFileSync(dest, bytes); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Catalog pages stop showing an uploaded MP4 of a block and start playing the block itself, live, in
<hyperframes-player>.164 of the 168 items switch over. The other 4 keep their video and the generator says which and why.
Why
The previews were recordings, published to the CDN by hand. That made them a second artifact to keep in sync with the registry, and it meant a reader could not scrub, pause, or inspect the thing they were about to install.
An earlier attempt to fix this shipped the previews as
.htmlfiles underdocs/publicand took every catalog page's preview down in production. That failure is what set the constraints this change is built around.How
Two constraints came out of probing the deployed docs host directly, one page per strategy:
docs/publicpublishes only JSON and image files..html,.js,.cssand.txtreturn 404 with no build error, so a preview shipped as an HTML file 404s in production while its page still serves 200.<hyperframes-player>written into a page never reaches the DOM. Nothing rewrites the inside of asrcDocdocument, and an external<script src>does execute.So each page carries one small bootstrap iframe. Inside it, the player loads from the CDN, fetches the composition from
/public/catalog/<type>/<slug>.json, and mounts it viasrcdoc.Assets are inlined as data URIs rather than copied next to the payload. A data URI is just a string in JSON, so the host's file-type restriction stops applying to fonts, scripts and models, and a preview never renders half-dressed while assets are still in flight.
scripts/generate-catalog-previews.tsgrew a direct-run guard because the payload generator imports its item discovery, and an unguardedmain()would render every preview on import.What still uses a video
blue-sweater-intro-videomacos-tahoe-liquid-glasstexture-mask-textcaption-blend-differencemainalready, unrelated to this changeTest plan
scripts/catalog-payload-assets.test.tscovers the reference matching and inlining. Both of its rules are pinned by a negative control: removing the leading-character rule fails one test, disabling the extension filter fails another. That regex had already been wrong twice, matching GLSL shader source assigned tovertSrcandurl(%23noise)filter references.Verified on this PR's preview deployment rather than locally, since the failure mode being fixed only appears once deployed.
Repo size
docs/public/catalogis 18 MB: payloads plus a shared, content-addressed asset directory.Assets are written once and linked rather than inlined per item. Which types can be linked was settled by fetching one file of each from a deployed preview:
docs/public.json,.png,.jpg,.webp,.svg.woff2,.wav,.mp4.glb.html,.js,.css,.txtAnything in the "no" rows still travels inside the payload as a data URI, because a link that 404s is worse than a larger payload.
Two passes are needed, not one. File references are rewritten as they are found, but compositions also arrive with their fonts already embedded as data URIs, which no reference scan sees. Those are pulled out too when they are large enough to be worth a request. Output is content-addressed, so regenerating an unchanged item produces no new blobs.