scripts: serve catalog previews from the docs site

Three scripts still reached upstream infrastructure, and running any of them
put its URLs back into the tree.

generate-catalog-pages emitted an absolute vendor CDN host into every catalog
page. The pages already checked in use root-relative /images/ paths, so a
regenerate reverted 306 of them; the base now matches what ships, and the docs
site serves the previews its own generator produces.

backfill-block-previews wrote a preview field into registry manifests from
that same CDN pattern. It is a one-shot migration nothing calls, and no
manifest carries the field it wrote. Gone.

upload-docs-images synced docs/images to an S3 bucket under an upstream AWS
profile. Its source directory does not exist, and the contributing guides
already say previews are served from the docs site and nothing is uploaded.
Gone, with the script entry and the comments that pointed at it.
This commit is contained in:
zooqueen
2026-08-13 18:10:50 -07:00
parent 1d910c40de
commit de0942fa49
8 changed files with 12 additions and 161 deletions
+3 -3
View File
@@ -17,9 +17,9 @@ lefthook-local.yml
.DS_Store
Thumbs.db
# Docs media — served from CDN, not committed.
# Regenerate with scripts/generate-{catalog,template}-previews.ts then upload
# with `bun run upload:docs-images`. Add explicit negations below for any
# Docs media — built at deploy time, not committed. Regenerate with
# scripts/generate-{catalog,template}-previews.ts; the docs site serves them
# from its own /images/ path. Add explicit negations below for any
# non-generated assets (logos, svgs) that should stay in the repo.
docs/images/
-1
View File
@@ -52,7 +52,6 @@
"generate:previews": "tsx scripts/generate-template-previews.ts",
"generate:catalog-previews": "tsx scripts/generate-catalog-previews.ts",
"package:codex-plugin": "node scripts/package-codex-plugin.mjs",
"upload:docs-images": "bash scripts/upload-docs-images.sh",
"prepare": "test -d .git && lefthook install || true"
},
"devDependencies": {
-120
View File
@@ -1,120 +0,0 @@
#!/usr/bin/env tsx
/**
* Backfill preview URLs in registry block + component manifests.
*
* - Blocks: adds `preview: { video, poster }` using the deterministic CDN pattern
* - Components: normalizes bare-string `preview` to `{ video }` object format
*
* Usage:
* npx tsx scripts/backfill-block-previews.ts # all items
* npx tsx scripts/backfill-block-previews.ts --dry-run # preview changes only
*/
import { readdirSync, readFileSync, writeFileSync } from "node:fs";
import { join, resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(scriptDir, "..");
const registryDir = resolve(repoRoot, "registry");
const CDN_BASE = "https://static.heygen.ai/frames-oss/docs/images/catalog";
const dryRun = process.argv.includes("--dry-run");
interface Preview {
video?: string;
poster?: string;
}
let updated = 0;
let skipped = 0;
function tryReadManifest(manifestPath: string): Record<string, unknown> | null {
try {
return JSON.parse(readFileSync(manifestPath, "utf-8"));
} catch {
return null;
}
}
function writeManifest(manifestPath: string, manifest: Record<string, unknown>): void {
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
}
function backfillBlocks() {
const blocksDir = join(registryDir, "blocks");
let entries: ReturnType<typeof readdirSync<string>>;
try {
entries = readdirSync(blocksDir, { withFileTypes: true });
} catch {
return;
}
for (const entry of entries) {
if (!entry.isDirectory()) continue;
const manifestPath = join(blocksDir, entry.name, "registry-item.json");
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) {
skipped++;
continue;
}
manifest.preview = preview;
if (dryRun) {
console.log(`[dry-run] ${entry.name}: would set preview →`, preview);
} else {
writeManifest(manifestPath, manifest);
}
updated++;
}
}
function normalizeComponents() {
const componentsDir = join(registryDir, "components");
let entries: ReturnType<typeof readdirSync<string>>;
try {
entries = readdirSync(componentsDir, { withFileTypes: true });
} catch {
return;
}
for (const entry of entries) {
if (!entry.isDirectory()) continue;
const manifestPath = join(componentsDir, entry.name, "registry-item.json");
const manifest = tryReadManifest(manifestPath);
if (!manifest) continue;
if (!manifest.preview) continue;
if (typeof manifest.preview === "string") {
manifest.preview = { video: manifest.preview };
if (dryRun) {
console.log(
`[dry-run] ${entry.name}: normalize string → { video: "${(manifest.preview as Preview).video}" }`,
);
} else {
writeManifest(manifestPath, manifest);
}
updated++;
} else {
skipped++;
}
}
}
backfillBlocks();
normalizeComponents();
console.log(
`\n${dryRun ? "[dry-run] " : ""}Done: ${updated} updated, ${skipped} already up-to-date`,
);
+4 -1
View File
@@ -27,7 +27,10 @@ const scriptDir = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(scriptDir, "..");
const registryDir = resolve(repoRoot, "registry");
const docsDir = resolve(repoRoot, "docs");
const catalogImageBase = "https://static.heygen.ai/frames-oss/docs/images/catalog";
// Previews resolve from the docs site's own /images/ path, produced by
// `bun run generate:catalog-previews` at deploy time. Root-relative, so the
// emitted pages carry no host and match what is already checked in.
const catalogImageBase = "/images/catalog";
// ── Types ──────────────────────────────────────────────────────────────────
+2 -2
View File
@@ -9,8 +9,8 @@
* - Components: renders the component's demo.html via a wrapper index.html
*
* Output: docs/images/catalog/<type>/<name>.png + <name>.mp4
* (docs/images/ is gitignored — files are served from the CDN. After running
* this script, run `bun run upload:docs-images` to publish.)
* (docs/images/ is gitignored — the docs site serves them from its own
* /images/ path, so a deploy runs this script rather than uploading.)
*
* Usage:
* npx tsx scripts/generate-catalog-previews.ts # all items
+2 -2
View File
@@ -6,8 +6,8 @@
* videos of each built-in template.
*
* Output: docs/images/templates/<id>.png + <id>.mp4
* (docs/images/ is gitignored — files are served from the CDN. After running
* this script, run `bun run upload:docs-images` to publish.)
* (docs/images/ is gitignored — the docs site serves them from its own
* /images/ path, so a deploy runs this script rather than uploading.)
*
* Usage:
* bun run generate:previews # all templates (PNG + MP4)
-31
View File
@@ -1,31 +0,0 @@
#!/usr/bin/env bash
#
# Upload docs/images/ to the HeyGen public CDN.
#
# Docs previews (mp4/png/gif) are served from https://static.heygen.ai/frames-oss/docs/images/
# rather than committed to the repo. After regenerating previews with
# `scripts/generate-catalog-previews.ts` or `scripts/generate-template-previews.ts`,
# run this script to publish the new files.
#
# Requires AWS credentials for the heygen engineering account (profile: engineering-767398024897).
# Contributors without AWS access: open a PR with the HTML/MDX changes and a
# maintainer will run the generators + this upload before merging.
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SRC="$REPO_ROOT/docs/images/"
DEST="s3://heygen-public/frames-oss/docs/images/"
PROFILE="${AWS_PROFILE:-engineering-767398024897}"
if [ ! -d "$SRC" ]; then
echo "No docs/images/ directory to upload — nothing to do."
exit 0
fi
echo "Uploading $SRC → $DEST (profile: $PROFILE)"
aws --profile "$PROFILE" s3 sync "$SRC" "$DEST" \
--cache-control "public, max-age=31536000, immutable" \
--metadata-directive REPLACE
echo "Done. Files are live at https://static.heygen.ai/frames-oss/docs/images/"
@@ -117,7 +117,7 @@ npx @hanzo/frames publish
**Catalog preview image** — The catalog card uses a PNG at `docs/images/catalog/{kind}/{name}.png` (where `{kind}` is `blocks` or `components`). Generate it from a snapshot, then:
- **Maintainers:** regenerate previews with `bun run generate:catalog-previews`; they are served from the docs site's own `/images/` path, so nothing is uploaded anywhere
- **External contributors:** attach the preview MP4 to your PR description. A maintainer will generate and upload the catalog image before merging.
- **External contributors:** attach the preview MP4 to your PR description. A maintainer will generate the catalog image before merging.
### Step 6: Ship