diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3346785d..81f8dbbeb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,8 +10,31 @@ concurrency: cancel-in-progress: true jobs: + changes: + name: Detect changes + runs-on: ubuntu-latest + timeout-minutes: 2 + outputs: + code: ${{ steps.filter.outputs.code }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + code: + - "packages/**" + - "scripts/**" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - "tsconfig*.json" + - "Dockerfile*" + build: name: Build + needs: changes + if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -28,6 +51,8 @@ jobs: typecheck: name: Typecheck + needs: changes + if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -45,6 +70,8 @@ jobs: test-core: name: "Test: core" + needs: changes + if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -61,6 +88,8 @@ jobs: test-engine: name: "Test: engine" + needs: changes + if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -77,6 +106,8 @@ jobs: test-runtime-contract: name: "Test: runtime contract" + needs: changes + if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest timeout-minutes: 10 steps: diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..ad887ec8d --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,35 @@ +name: Docs + +on: + pull_request: + paths: + - "docs/**" + - "DOCS_GUIDELINES.md" + push: + branches: [main] + paths: + - "docs/**" + +concurrency: + group: docs-${{ github.ref }} + cancel-in-progress: true + +jobs: + validate: + name: Validate docs + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Validate build + working-directory: docs + run: npx mint validate + + - name: Check broken links + working-directory: docs + run: npx mint broken-links diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index c131bf8c9..99f8f9708 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -7,7 +7,27 @@ on: - main jobs: + changes: + name: Detect changes + runs-on: ubuntu-latest + timeout-minutes: 2 + outputs: + code: ${{ steps.filter.outputs.code }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + code: + - "packages/**" + - "scripts/**" + - "Dockerfile*" + - "pnpm-lock.yaml" + regression-shards: + needs: changes + if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest timeout-minutes: 40 strategy: @@ -83,11 +103,15 @@ jobs: # Summary job — matches the required check name in branch protection regression: runs-on: ubuntu-latest - needs: regression-shards + needs: [changes, regression-shards] if: always() steps: - - name: Check shard results + - name: Check results run: | + if [ "${{ needs.changes.outputs.code }}" != "true" ]; then + echo "No code changes — skipping regression (auto-pass)" + exit 0 + fi if [ "${{ needs.regression-shards.result }}" != "success" ]; then echo "One or more regression shards failed" exit 1 diff --git a/DOCS_GUIDELINES.md b/DOCS_GUIDELINES.md new file mode 100644 index 000000000..89a915ba9 --- /dev/null +++ b/DOCS_GUIDELINES.md @@ -0,0 +1,148 @@ +# Documentation Guidelines + +Standards for writing and maintaining Hyperframes documentation. Based on patterns from Remotion, Stripe, Tailwind CSS, and Astro. + +## Core Principles + +1. **One-sentence intro rule** — Every page opens with a single sentence telling the reader what this page helps them do or understand. No preamble, no history. + +2. **Outcome before implementation** — Show what the code produces (rendered result, terminal output, file structure) before showing the code itself. + +3. **Show, don't tell** — Use concrete examples with realistic values. Never use `foo`/`bar`/`baz`. Prefer a working HTML snippet over a description of what to write. + +4. **Two content modes** — Guides build narratives with progressive complexity. References enable scanning with standardized structure. Never mix them. + +5. **No dead ends** — Every page links forward (next steps), backward (prerequisites), and sideways (related concepts). Readers should never reach a page with nowhere to go. + +## Page Structure + +### Guides (concepts/, guides/) + +``` +Title +├── One-sentence purpose statement +├── What this looks like (output, demo, or visual) +├── Minimal working example +├── Deeper explanation with progressive complexity +├── Common patterns / best practices +├── Warnings and pitfalls (sparingly) +└── Next steps (cards or links to related pages) +``` + +### Reference pages (reference/) + +``` +Title +├── One-sentence definition +├── Complete attribute/API table +├── Detailed section per item (type, default, description, example) +├── Rules and constraints +└── Related pages +``` + +### Package pages (packages/) + +``` +Title +├── One-line description + install command +├── When to use this package (and when NOT to) +├── Key features list +├── Minimal usage example with expected output +├── Configuration reference +└── Related packages +``` + +## Writing Style + +- **Second person, active voice, imperative mood**: "Use X to do Y." Not "The developer should consider using X." +- **Present tense**: "The runtime manages media playback." Not "The runtime will manage..." +- **Be direct**: "This breaks rendering." Not "This may potentially cause issues with the rendering pipeline." +- **Prerequisites at point of need**: State requirements where they matter, not in a wall at the top. +- **Conversational but precise**: Friendly tone, exact technical details. + +## Code Examples + +### Always annotate code blocks + +```mdx +```html index.html +
+```​ +``` + +The filename after the language tag tells readers where the code goes. + +### Use numbered comments for multi-step code + +```javascript +// 1. Create a paused timeline +const tl = gsap.timeline({ paused: true }); + +// 2. Add animations +tl.from("#title", { opacity: 0, y: -50, duration: 1 }, 0); + +// 3. Register the timeline +window.__timelines["my-video"] = tl; +``` + +### Show expected output + +After CLI commands, show what the user should see: + +```bash +npx hyperframes dev +# ✓ Server running at http://localhost:3000 +# ✓ Watching for changes... +``` + +### Use CodeGroup for multi-platform commands + +```mdx + +```bash macOS +brew install ffmpeg +```​ +```bash Ubuntu +sudo apt install ffmpeg +```​ + +``` + +## Mintlify Components — When to Use + +| Component | Use When | +|-----------|----------| +| `` | Sequential setup or tutorial instructions | +| `` | Same action across platforms/languages | +| `` | Alternative approaches with equal weight | +| `` / `` | Navigation to related pages, next steps | +| `` | FAQ or optional detail that would bloat the page | +| `` | Non-obvious behavior the reader should know | +| `` | Something that will break if ignored | +| `` | Helpful shortcut or best practice | +| `` | Context that aids understanding | +| `` | File/directory structure | +| `` | Screenshots or diagrams with captions | + +### Callout budget: max 2-3 per page + +More than 3 callouts creates alert fatigue and readers skip them all. Reserve `` for things that genuinely break. Use inline prose for tips. + +## Cross-Linking + +- **Link at the point of curiosity**: When you mention a concept that has its own page, link it immediately. Don't hoard links. +- **"See also" at page bottom**: Only for genuinely related content that doesn't fit inline. +- **Next steps cards**: End guide pages with `` links to logical next pages. + +## File Conventions + +- All doc pages are `.mdx` (not `.md`) +- Use kebab-case for filenames: `frame-adapters.mdx`, not `frameAdapters.mdx` +- Frontmatter requires `title` and `description` +- Description should be under 160 characters (used for SEO/social) + +## Maintenance + +- Docs live in the repo at `/docs` and deploy automatically on merge to `main` +- PRs that change user-facing behavior should update relevant doc pages +- Run `mint validate` and `mint broken-links` before pushing doc changes diff --git a/docs/concepts/compositions.mdx b/docs/concepts/compositions.mdx new file mode 100644 index 000000000..ea9872163 --- /dev/null +++ b/docs/concepts/compositions.mdx @@ -0,0 +1,161 @@ +--- +title: Compositions +description: "The fundamental building block of a Hyperframes video." +--- + +A composition is an HTML document that defines a video timeline. Every clip -- video, image, audio -- lives inside a composition. + +## Structure + +Every composition needs a root element with `data-composition-id`: + +```html index.html +
+ +
+``` + +The `index.html` file is the top-level composition. It can contain nested compositions within it. Any composition can be imported into another -- there is no special "root" type. + +## Clip Types + +A clip is any discrete block on the timeline, represented as an HTML element with [data attributes](/concepts/data-attributes): + +- `