Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ on:
paths:
- "docs/**"
- "DOCS_GUIDELINES.md"
- "packages/core/schemas/**"
- "scripts/sync-schemas.ts"
push:
branches: [main]
paths:
- "docs/**"
- "DOCS_GUIDELINES.md"
- "packages/core/schemas/**"
- "scripts/sync-schemas.ts"

concurrency:
group: docs-${{ github.ref }}
Expand All @@ -27,6 +31,9 @@ jobs:
with:
node-version: 22

- name: Check schema mirror (core → docs)
run: npx tsx scripts/sync-schemas.ts --check

- name: Validate build
working-directory: docs
run: npx mint validate
Expand Down
45 changes: 45 additions & 0 deletions docs/schema/hyperframes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://hyperframes.heygen.com/schema/hyperframes.json",
"title": "Hyperframes Project Config",
"description": "Per-project configuration for a Hyperframes project (hyperframes.json). Tells `hyperframes add` which registry to pull items from and where to drop them in the project tree. Created by `hyperframes init`; users may edit it to point at custom registries or reshape their project layout.",
"type": "object",
"required": ["registry", "paths"],
"additionalProperties": false,
"properties": {
"$schema": {
"type": "string",
"format": "uri",
"description": "JSON Schema URL — https://hyperframes.heygen.com/schema/hyperframes.json."
},
"registry": {
"type": "string",
"format": "uri",
"minLength": 1,
"description": "Base URL of the registry to pull items from. Point at the official Hyperframes registry or a custom one."
},
"paths": {
"type": "object",
"description": "Target paths for each item type, relative to the project root.",
"required": ["blocks", "components", "assets"],
"additionalProperties": false,
"properties": {
"blocks": {
"type": "string",
"minLength": 1,
"description": "Where `hyperframes:block` items land. Defaults to `compositions`."
},
"components": {
"type": "string",
"minLength": 1,
"description": "Where `hyperframes:component` items land. Defaults to `compositions/components`."
},
"assets": {
"type": "string",
"minLength": 1,
"description": "Where asset files (images, fonts, videos) land. Defaults to `assets`."
}
}
}
}
}
141 changes: 141 additions & 0 deletions docs/schema/registry-item.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://hyperframes.heygen.com/schema/registry-item.json",
"title": "Hyperframes Registry Item",
"description": "Manifest for a single distributable item (example, block, or component).",
"type": "object",
"required": ["name", "type", "title", "description", "files"],
"properties": {
"$schema": {
"type": "string",
"format": "uri"
},
"name": {
"type": "string",
"pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$",
"description": "Item name in kebab-case, must start and end with alphanumeric."
},
"type": {
"type": "string",
"enum": ["hyperframes:example", "hyperframes:block", "hyperframes:component"]
},
"title": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string",
"minLength": 1
},
"tags": {
"type": "array",
"items": { "type": "string", "minLength": 1 }
},
"author": {
"type": "string",
"minLength": 1
},
"license": {
"type": "string",
"minLength": 1,
"description": "SPDX license identifier (e.g. \"Apache-2.0\", \"MIT\")."
},
"minCliVersion": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$",
"description": "Minimum `hyperframes` CLI version required to install this item."
},
"deprecated": {
"type": "string",
"minLength": 1,
"description": "If set, the item is deprecated; the value is the reason or migration note."
},
"dimensions": {
"type": "object",
"required": ["width", "height"],
"additionalProperties": false,
"properties": {
"width": { "type": "integer", "minimum": 1 },
"height": { "type": "integer", "minimum": 1 }
}
},
"duration": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Duration in seconds. Must be > 0."
},
"registryDependencies": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$"
}
},
"files": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["path", "target", "type"],
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"minLength": 1,
"description": "Source path, relative to registry-item.json."
},
"target": {
"type": "string",
"minLength": 1,
"description": "Destination path in the user's project, relative to project root. Must not traverse outside the project (no `..` segments, no absolute paths).",
"not": {
"anyOf": [
{ "pattern": "(^|[/\\\\])\\.\\.([/\\\\]|$)" },
{ "pattern": "^[/\\\\]" },
{ "pattern": "^[A-Za-z]:[/\\\\]" }
]
}
},
"type": {
"type": "string",
"enum": [
"hyperframes:composition",
"hyperframes:asset",
"hyperframes:snippet",
"hyperframes:style",
"hyperframes:timeline"
]
}
}
}
},
"preview": {
"type": "object",
"additionalProperties": false,
"properties": {
"video": { "type": "string" },
"poster": { "type": "string" }
}
},
"relatedSkill": {
"type": "string",
"minLength": 1
}
},
"allOf": [
{
"if": {
"required": ["type"],
"properties": { "type": { "const": "hyperframes:component" } }
},
"then": {
"not": {
"anyOf": [{ "required": ["dimensions"] }, { "required": ["duration"] }]
}
},
"else": {
"required": ["dimensions", "duration"]
}
}
]
}
45 changes: 45 additions & 0 deletions docs/schema/registry.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://hyperframes.heygen.com/schema/registry.json",
"title": "Hyperframes Registry Manifest",
"description": "Top-level manifest describing all items in a Hyperframes registry.",
"type": "object",
"required": ["name", "homepage", "items"],
"additionalProperties": false,
"properties": {
"$schema": {
"type": "string",
"format": "uri"
},
"name": {
"type": "string",
"minLength": 1,
"description": "Registry name (e.g. \"hyperframes\")."
},
"homepage": {
"type": "string",
"format": "uri",
"description": "Registry homepage URL."
},
"items": {
"type": "array",
"description": "Items in this registry. Each entry is a shorthand reference; the full item manifest lives at <type-dir>/<name>/registry-item.json.",
"items": {
"type": "object",
"required": ["name", "type"],
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$",
"description": "Item name in kebab-case, must start and end with alphanumeric."
},
"type": {
"type": "string",
"enum": ["hyperframes:example", "hyperframes:block", "hyperframes:component"]
}
}
}
}
}
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"build:hyperframes-runtime:modular": "bun run --filter @hyperframes/core build:hyperframes-runtime:modular",
"verify:packed-manifests": "node scripts/verify-packed-manifests.mjs",
"set-version": "tsx scripts/set-version.ts",
"sync-schemas": "tsx scripts/sync-schemas.ts",
"sync-schemas:check": "tsx scripts/sync-schemas.ts --check",
"lint": "oxlint . && tsx scripts/lint-skills.ts",
"lint:skills": "tsx scripts/lint-skills.ts",
"lint:fix": "oxlint --fix .",
Expand Down
60 changes: 60 additions & 0 deletions scripts/sync-schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env tsx
/**
* Mirror JSON Schemas from `packages/core/schemas/` into `docs/schema/` so
* Mintlify serves them at `https://hyperframes.heygen.com/schema/*`. The core
* copies stay authoritative — they're exported from `@hyperframes/core` for
* npm consumers — and this script is the single contract that prevents the
* docs mirror from drifting.
*
* Usage:
* bun run sync-schemas # copy core → docs
* bun run sync-schemas --check # exit non-zero if copies are stale (CI)
*
* `docs/schema/hyperframes.json` is authored directly in docs (no source in
* core) so it's skipped by this script.
*/

import { readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";

const ROOT = join(import.meta.dirname, "..");
const SOURCE_DIR = join(ROOT, "packages/core/schemas");
const TARGET_DIR = join(ROOT, "docs/schema");
const MIRRORED = ["registry.json", "registry-item.json"];

function main() {
const checkOnly = process.argv.includes("--check");
let drift = 0;

for (const name of MIRRORED) {
const source = readFileSync(join(SOURCE_DIR, name), "utf-8");
const targetPath = join(TARGET_DIR, name);
const target = (() => {
try {
return readFileSync(targetPath, "utf-8");
} catch {
return null;
}
})();

if (target === source) {
console.log(` ✓ ${name} in sync`);
continue;
}

drift++;
if (checkOnly) {
console.error(` ✗ ${name} out of sync (run \`bun run sync-schemas\` to fix)`);
continue;
}
writeFileSync(targetPath, source);
console.log(` → ${name} updated`);
}

if (checkOnly && drift > 0) {
console.error(`\n${drift} schema${drift === 1 ? "" : "s"} drifted from source.`);
process.exit(1);
}
}

main();
Loading