feat(registry): eight ad templates show their video preview in the catalog (#4979)

* feat(registry): eight ad templates show their video preview in the catalog

* refactor(scripts): the preview backfill reuses the shared entrypoint guard
This commit is contained in:
Miguel Ángel
2026-10-04 01:27:10 +00:00
committed by GitHub
parent cd1a34ceca
commit d2398d686a
11 changed files with 82 additions and 22 deletions
+1 -1
View File
@@ -52,7 +52,7 @@
"player:perf": "bun run --filter @hyperframes/player perf",
"format:check": "oxfmt --check .",
"knip": "knip",
"test:scripts": "node --import tsx --test scripts/animejs-v4-guidance.test.mjs scripts/check-tracked-artifacts.test.mjs scripts/check-registry-set-delta.test.mjs scripts/check-no-main-deletions.test.mjs scripts/check-pr-captures.test.mjs scripts/check-comment-citations.test.mjs scripts/comments-workflow.test.mjs scripts/comment-ratchet.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.test.mjs scripts/check-media-use-copy-parity.test.mjs scripts/check-svg-sanitize-parity.test.mjs scripts/check-media-use-svg-sanitize-generated.test.mjs scripts/check-package-cycles.test.mjs scripts/check-cli-process-ownership.test.mjs scripts/check-large-files.test.mjs scripts/prune-fallow-audit-caches.test.mjs scripts/package-subpaths.test.mjs scripts/validate-release-channel.test.mjs scripts/publish-workflow.test.mjs scripts/pr-edit-concurrency.test.mjs scripts/merge-queue-workflows.test.mjs scripts/install-workspace-dependencies.test.mjs scripts/draft-changelog.test.ts scripts/set-version.test.ts scripts/release-prepare.test.ts scripts/cli-options.test.ts scripts/changelog-weekly.test.ts scripts/claude-plugin-compression.test.ts scripts/catalog-payload-assets.test.ts scripts/host-registry-assets.test.ts scripts/catalog-preview-temp.test.ts scripts/catalog-hosted-files.test.ts scripts/player-cdn-pin.test.ts scripts/studio-runtime-smoke.test.mjs scripts/verify-packed-manifests.test.mjs scripts/lint-skills.test.mjs scripts/creator-editing-recipes.test.mjs packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs packages/core/scripts/writeGeneratedFile.test.ts scripts/catalog-publication.test.mjs scripts/ci/resolve-workflow-pr.test.mjs scripts/ci/base-file.test.mjs scripts/check-catalog-source-pr.test.mjs scripts/generate-registry-items.test.ts scripts/catalog-drift.test.ts scripts/catalog-fetch-mirror.test.ts scripts/catalog-script-inlining.test.ts scripts/catalog-detail.test.ts scripts/generate-catalog-pages.test.ts scripts/verify-catalog-payloads.test.ts scripts/registry-skill-files.test.ts scripts/creator-editing-capabilities.test.mjs scripts/generate-catalog-previews.test.ts scripts/registry-primitive-payloads.test.ts registry/components/pan-stations/pan-stations.test.mjs && vitest run scripts/catalog/ scripts/contrastRatchet.test.ts scripts/generate-catalog-payloads.test.ts",
"test:scripts": "node --import tsx --test scripts/animejs-v4-guidance.test.mjs scripts/check-tracked-artifacts.test.mjs scripts/check-registry-set-delta.test.mjs scripts/check-no-main-deletions.test.mjs scripts/check-pr-captures.test.mjs scripts/check-comment-citations.test.mjs scripts/comments-workflow.test.mjs scripts/comment-ratchet.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.test.mjs scripts/check-media-use-copy-parity.test.mjs scripts/check-svg-sanitize-parity.test.mjs scripts/check-media-use-svg-sanitize-generated.test.mjs scripts/check-package-cycles.test.mjs scripts/check-cli-process-ownership.test.mjs scripts/check-large-files.test.mjs scripts/prune-fallow-audit-caches.test.mjs scripts/package-subpaths.test.mjs scripts/validate-release-channel.test.mjs scripts/publish-workflow.test.mjs scripts/pr-edit-concurrency.test.mjs scripts/merge-queue-workflows.test.mjs scripts/install-workspace-dependencies.test.mjs scripts/draft-changelog.test.ts scripts/set-version.test.ts scripts/release-prepare.test.ts scripts/cli-options.test.ts scripts/changelog-weekly.test.ts scripts/claude-plugin-compression.test.ts scripts/catalog-payload-assets.test.ts scripts/host-registry-assets.test.ts scripts/catalog-preview-temp.test.ts scripts/backfill-block-previews.test.ts scripts/catalog-hosted-files.test.ts scripts/player-cdn-pin.test.ts scripts/studio-runtime-smoke.test.mjs scripts/verify-packed-manifests.test.mjs scripts/lint-skills.test.mjs scripts/creator-editing-recipes.test.mjs packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs packages/core/scripts/writeGeneratedFile.test.ts scripts/catalog-publication.test.mjs scripts/ci/resolve-workflow-pr.test.mjs scripts/ci/base-file.test.mjs scripts/check-catalog-source-pr.test.mjs scripts/generate-registry-items.test.ts scripts/catalog-drift.test.ts scripts/catalog-fetch-mirror.test.ts scripts/catalog-script-inlining.test.ts scripts/catalog-detail.test.ts scripts/generate-catalog-pages.test.ts scripts/verify-catalog-payloads.test.ts scripts/registry-skill-files.test.ts scripts/creator-editing-capabilities.test.mjs scripts/generate-catalog-previews.test.ts scripts/registry-primitive-payloads.test.ts registry/components/pan-stations/pan-stations.test.mjs && vitest run scripts/catalog/ scripts/contrastRatchet.test.ts scripts/generate-catalog-payloads.test.ts",
"typecheck:scripts": "tsc --noEmit -p scripts/tsconfig.json",
"test:skills": "HYPERFRAMES_MEDIA_HOME_REQUIRED=1 node --import ./packages/cli/scripts/test-home.mjs --test 'skills/**/*.test.mjs' 'packages/cli/src/media-use/**/*.test.mjs'",
"generate:previews": "tsx scripts/generate-template-previews.ts",
@@ -138,5 +138,9 @@
"target": "TEMPLATE.md",
"type": "hyperframes:asset"
}
]
],
"preview": {
"video": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/ai-chat-reveal/preview.mp4",
"poster": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/ai-chat-reveal/poster.jpg"
}
}
@@ -42,5 +42,9 @@
"target": "TEMPLATE.md",
"type": "hyperframes:asset"
}
]
],
"preview": {
"video": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/chatgpt-exchange/preview.mp4",
"poster": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/chatgpt-exchange/poster.jpg"
}
}
@@ -57,5 +57,9 @@
"target": "TEMPLATE.md",
"type": "hyperframes:asset"
}
]
],
"preview": {
"video": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/claude-exchange/preview.mp4",
"poster": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/claude-exchange/poster.jpg"
}
}
@@ -206,5 +206,9 @@
"target": "TEMPLATE.md",
"type": "hyperframes:asset"
}
]
],
"preview": {
"video": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/message-thread-reveal/preview.mp4",
"poster": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/message-thread-reveal/poster.jpg"
}
}
@@ -206,5 +206,9 @@
"target": "TEMPLATE.md",
"type": "hyperframes:asset"
}
]
],
"preview": {
"video": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/notes-reveal/preview.mp4",
"poster": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/notes-reveal/poster.jpg"
}
}
@@ -117,5 +117,9 @@
"target": "TEMPLATE.md",
"type": "hyperframes:asset"
}
]
],
"preview": {
"video": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/notification-cascade/preview.mp4",
"poster": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/notification-cascade/poster.jpg"
}
}
@@ -140,5 +140,9 @@
"target": "TEMPLATE.md",
"type": "hyperframes:asset"
}
]
],
"preview": {
"video": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/share-sheet-carousel/preview.mp4",
"poster": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/share-sheet-carousel/poster.jpg"
}
}
@@ -52,5 +52,9 @@
"target": "TEMPLATE.md",
"type": "hyperframes:asset"
}
]
],
"preview": {
"video": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/slack-notification-ad/preview.mp4",
"poster": "https://static.heygen.ai/hyperframes/templates/promoted/254fe4bd8a3f00c1e70ac5e38a1bce25060f7590/slack-notification-ad/poster.jpg"
}
}
+21
View File
@@ -0,0 +1,21 @@
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { missingBlockPreview } from "./backfill-block-previews.js";
describe("backfill block previews", () => {
it("fills a block that declares no preview with the catalog CDN pattern", () => {
assert.deepEqual(missingBlockPreview("app-showcase", undefined), {
video: "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/app-showcase.mp4",
poster:
"https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/app-showcase.png",
});
});
it("keeps a declared preview that points somewhere else", () => {
const promoted = {
video: "https://static.heygen.ai/hyperframes/templates/promoted/abc/notes-reveal/preview.mp4",
poster: "https://static.heygen.ai/hyperframes/templates/promoted/abc/notes-reveal/poster.jpg",
};
assert.equal(missingBlockPreview("notes-reveal", promoted), null);
});
});
+20 -13
View File
@@ -2,7 +2,7 @@
/**
* Backfill preview URLs in registry block + component manifests.
*
* - Blocks: adds `preview: { video, poster }` using the deterministic CDN pattern
* - Blocks: adds `preview: { video, poster }` using the deterministic CDN pattern, only where none is declared
* - Components: normalizes bare-string `preview` to `{ video }` object format
*
* Usage:
@@ -13,6 +13,7 @@
import { readdirSync, readFileSync, writeFileSync, type Dirent } from "node:fs";
import { join, resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { isEntrypoint } from "./entrypoint.ts";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(scriptDir, "..");
@@ -42,6 +43,15 @@ function writeManifest(manifestPath: string, manifest: Record<string, unknown>):
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
}
/** The preview to write for a block, or null: a declared preview may point elsewhere and is kept. */
export function missingBlockPreview(name: string, existing: unknown): Preview | null {
if (existing) return null;
return {
video: `${CDN_BASE}/blocks/${name}.mp4`,
poster: `${CDN_BASE}/blocks/${name}.png`,
};
}
function backfillBlocks() {
const blocksDir = join(registryDir, "blocks");
let entries: Dirent[];
@@ -57,13 +67,8 @@ function backfillBlocks() {
const manifest = tryReadManifest(manifestPath);
if (!manifest) continue;
const preview: Preview = {
video: `${CDN_BASE}/blocks/${entry.name}.mp4`,
poster: `${CDN_BASE}/blocks/${entry.name}.png`,
};
const existing = manifest.preview as Preview | undefined;
if (existing?.video === preview.video && existing?.poster === preview.poster) {
const preview = missingBlockPreview(entry.name, manifest.preview);
if (!preview) {
skipped++;
continue;
}
@@ -112,9 +117,11 @@ function normalizeComponents() {
}
}
backfillBlocks();
normalizeComponents();
if (isEntrypoint(import.meta.url)) {
backfillBlocks();
normalizeComponents();
console.log(
`\n${dryRun ? "[dry-run] " : ""}Done: ${updated} updated, ${skipped} already up-to-date`,
);
console.log(
`\n${dryRun ? "[dry-run] " : ""}Done: ${updated} updated, ${skipped} already up-to-date`,
);
}