diff --git a/docs/concepts/compositions.mdx b/docs/concepts/compositions.mdx index 5edf19dd0..2e3f29156 100644 --- a/docs/concepts/compositions.mdx +++ b/docs/concepts/compositions.mdx @@ -166,7 +166,7 @@ animation. Never use a script to play, pause, or seek a media element, and never use one to show or hide a clip based on time. The framework already does that from the data attributes, and a script doing it too will fight the framework. See - [Common Mistakes](/guides/common-mistakes) for what that looks like. + [Common Mistakes](/guides/troubleshooting) for what that looks like. ## Reuse one composition with different content diff --git a/docs/concepts/determinism.mdx b/docs/concepts/determinism.mdx index 65ab34553..dc3aeff4c 100644 --- a/docs/concepts/determinism.mdx +++ b/docs/concepts/determinism.mdx @@ -94,4 +94,4 @@ that stutters in preview still renders perfectly — see - [Render to MP4](/guides/rendering) - [Compositions](/concepts/compositions) - [@hyperframes/producer](/packages/producer) -- [Common mistakes that break determinism](/guides/common-mistakes) +- [Common mistakes that break determinism](/guides/troubleshooting) diff --git a/docs/contributing/canary-rollouts.mdx b/docs/contributing/canary-rollouts.mdx index f36d68cbd..daa765ad8 100644 --- a/docs/contributing/canary-rollouts.mdx +++ b/docs/contributing/canary-rollouts.mdx @@ -3,26 +3,20 @@ title: "Canary rollouts" description: "Ship a change to a percentage of installs instead of all-or-nothing." --- -Most flags in this repo are binary: a feature is off (and therefore never -exercised on real traffic) or on for everyone (and therefore a fleet-wide -bet). A canary is the rung in between — the same change, enabled for a stable -slice of installs, ramped as the signal holds. +Most flags in this repo are binary: a change is off, or on for everyone. A +canary is the rung in between — the same change, enabled for a stable slice of +installs, ramped as the signal holds. - **Canaries are part of telemetry, not a separate system.** A canary is a - *measured* rollout: a slice is enrolled specifically so it can be compared - against everyone else, and the comparison is what makes ramping safe. An - install that reports nothing cannot be compared, so **opting out of telemetry - opts you out of canaries** — via `hyperframes telemetry disable`, - `HYPERFRAMES_NO_TELEMETRY=1`, `DO_NOT_TRACK=1`, a dev build, or Studio's - `hyperframes-studio:telemetryDisabled`. See the - [`telemetry` command](/packages/cli#telemetry) for what is collected and how - to turn it off; everything on this page sits behind that switch. + A canary is a *measured* rollout: a slice is enrolled so it can be compared + against everyone else. So **opting out of telemetry opts you out of + canaries** — an opted-out install is never bucketed at all. See the + [`telemetry` command](/packages/cli#telemetry) for the opt-out routes. ## Add one -**1. Register it at 0%.** In `packages/core/src/canaryRegistry.ts`: +**1. Register it at 0%** in `packages/core/src/canaryRegistry.ts`: ```ts { @@ -48,232 +42,40 @@ if (isCanaryEnabled("my-feature")) { } ``` -That is the whole API. The percentage lives in the registry, never at the -call site. +That is the whole API. The percentage lives in the registry, never at the call +site. **3. Ramp it** by editing `percentage` in a patch release: `0 → 5 → 25 → 100`. +Widening is inclusive — everyone already in the 10 stays in the 25, so a +before/after comparison survives the ramp. Do not rename a live canary: the +name is part of the bucket hash, so renaming reshuffles the cohort mid-rollout. -**4. Delete it** once it is at 100 and holding — both the registry entry and -the branch it guarded. `sunsetAfter` exists to force this: the scheduled -**Canary sunset** workflow runs weekly and fails once the date passes, naming -the overdue rollout and its owner in the run log. It does not notify anyone — -watch the workflow if you own a canary. +**4. Delete it** at 100 and holding — the registry entry *and* the branch it +guarded. The scheduled **Canary sunset** workflow enforces this: it runs weekly +and fails once `sunsetAfter` passes, naming the overdue rollout and its owner in +the run log. It notifies nobody, so watch it if you own a canary. Run it +yourself with `bun scripts/check-canary-sunset.ts`. -It is a scheduled job rather than a PR check on purpose. A current-date -assertion in the unit suite would redden builds for authors who changed -nothing related, on a calendar date, with no fix available to them — so the -failure is routed to the person who can actually ramp or remove the canary. -Run it yourself with `bun scripts/check-canary-sunset.ts`. - -## Overriding +## Override one ```bash HF_CANARY_MY_FEATURE=on # or off / true / false / 1 / 0 / yes / no ``` -Upper-snake-case the name. An override always wins over the percentage, in -both directions — use it for support escalations, dogfooding, bisects, or a -panic-off. +Upper-snake-case the name. In Studio, use `?hf_canary_my_feature=on`. An +override always wins over the percentage, in both directions — escalations, +dogfooding, bisects, a panic-off. It is also the way to exercise a canary with +telemetry off. -## Measuring +Everything else fails closed below 100%: no bucket seed, an unregistered name, +or a CI machine all resolve to *not enrolled*. At exactly 100% those exclusions +stop applying, so nothing takes the new path for the first time at deletion. -Every telemetry event carries the assignment as a flag-shaped property: +## Remove one from your machine -``` -$feature/canary-my-feature: "true" | "false" -``` - -`$feature/` is the de-facto flag-property convention in analytics -tooling, so whoever operates the telemetry backend can split any metric by -cohort with **nothing configured server-side** — while the decision itself -still happens locally and offline, which the render path requires. -(Assignments ride the same anonymous, opt-out telemetry pipeline as every -other event — and disabling telemetry disables the **enrolment**, not just the -reporting: an opted-out install is never bucketed at all. See the note at the -top of this page.) - -Two details worth knowing: - -- **Both arms are emitted.** A non-enrolled install reports `"false"`, not a - missing property. Absent means *this build predates the canary*, which is a - different fact from *this install is control* — collapsing them makes a ramp - unreadable. -- **Keys are namespaced with `canary-`.** The `$feature/` namespace is shared - with real product feature flags elsewhere in the analytics pipeline. The - infix guarantees a canary can never alias one and fight it for the same - property. - -## Cumulative exposure — the number that actually bounds blast radius - -The instantaneous share holds at the target forever: enrolment is a pure -function of `(feature, bucketSeed, percentage)` and fresh ids are uniformly -random, so ~10% of active installs and ~10% of renders are enrolled on any -given day. That part does not drift. - -**The cumulative set does grow.** Install ids churn — measured on the desktop -render population, there are ~25× more distinct ids over 30 days than in any -single day. Ten percent of a pool that keeps turning over is a steadily larger -group of installs that have been enrolled *at some point*. If a single person -cycles through N ids during a rollout, their chance of having been exposed is -`1 − (1 − p)^N`, so at 10%: 19% after two ids, 41% after five. - -So the number that bounds blast radius is *distinct installs ever enrolled -during the window*, not the instantaneous rate. Two practical consequences: - -- **Keep canaries short.** Drift compounds with time; a 5-day window at 10% is - far tighter than a 60-day one. -- **The percentage is not the safety mechanism.** It bounds *initial* exposure - and decays from there. Per-render verification and per-install circuit - breakers are what actually bound harm. A breaker's tripped state lives in - `install-state.json`, separate from `config.json` and merged back in on every - read, so a `config.json` re-mint cannot re-enrol an install into a path that - already failed it. Deleting `~/.hyperframes` clears both, deliberately — - that is the user's reset. - -For *measurement* — "is this feature better?" — churn is harmless: re-bucketing -is random, so it adds noise, not bias. It is specifically the blast-radius -guarantee that degrades. - -## Calibration: validating the mechanism in the wild - -Two inert canaries — `calibration-10` (10%) and `calibration-50` (50%) — gate -nothing and exist only to prove the mechanism behaves as designed on real -traffic. Their percentages stay FIXED for the whole window, which is what -makes check 3 below meaningful: while a percentage is constant, a cohort flip -is a bug, whereas during a real ramp a `false → true` flip is correct and -expected. - -Four checks, written down before the data arrives so the read is not post-hoc. -(The maintainers monitor these on an internal dashboard; the definitions live -here so the experiment's terms are public and fixed.) - -**1. Accuracy — does 10% mean 10%?** Measured install-weighted AND -event-weighted separately: render volume is heavily skewed toward a few heavy -installs, so the two can differ even when bucketing is perfect. Install share -is the one that must land on target. - -**2. Drift — does cumulative exposure climb?** Measured over widening windows -(1/7/14/30 days). The instantaneous share should stay flat at 10%; the -cumulative enrolled-install count should grow with id churn. - -**3. Stability — does any install ever change cohort?** MUST be zero. A single -id reporting both `true` and `false` at a fixed percentage means something is -broken: memoization, a registry edit mid-window, or two code paths -disagreeing. One innocent explanation to rule out first on a small-nonzero -read: events carry the assignment but not the decision *reason*, so a dev -toggling `HF_CANARY_CALIBRATION_10=on/off` mid-window is indistinguishable -from a real flip. Emitting a reason property is deliberately skipped — add it -only if this check comes back dirty. - -**4. Cross-surface agreement — do CLI and Studio agree for the same install?** -A CLI-launched Studio adopts the CLI's id, so the same install must report the -same cohort on both. Disagreement means the two bindings have diverged. This -compares the *value reported per surface* — any disagreement here is also a -check-3 flip, so this check's job is attribution: it isolates the flips that -are binding divergence rather than within-surface instability. - -**Independence bonus:** overlap between `calibration-10` and `calibration-50` -should be ~5% of installs (p1 x p2), not ~10% (which would mean the slices are -correlated and every canary hits the same unlucky cohort). - -### What passing looks like, and what cannot be fixed - -Checks 1, 3 and 4 should pass outright — they are properties of the design, -and failing any of them is a bug to fix before shipping a real rollout. - -Check 2 will NOT come back flat, and that is expected rather than a defect. -Per-install cohorts never flip, but a *person* who wipes their config gets a -new id and a fresh roll of the dice. Preventing that entirely needs a stable -identity across resets, and both candidates were rejected: hardware -fingerprinting correlates the cohort with hardware (fatal for a rendering -experiment, and it survives uninstall), and account identity covers only -~3.6% of local rendering installs. So the drift itself stands as a measured, -accepted limit — but its worst consequence is mitigated, and its size is now -directly measurable rather than inferred: - -- **Cohorts survive a config re-mint.** Canaries bucket on a dedicated - `bucketSeed` — not the telemetry id — held in `install-state.json` beside - `config.json` and write-once (the first install's seed wins forever). This - matters because `config.json` is rewritten on every command and every - render, and any parse/permission/IO failure makes the CLI mint a fresh - identity. The seed is never emitted, so it does not link the old id to the - new one. -- **Deleting `~/.hyperframes` clears the cohort too, deliberately.** The seed - does not live outside the config directory, so the user's reset is a real - reset. A seed that outlived it would be a persistent identifier defeating - the only lever they have — see [the removal path](#removing-your-canary-state). -- **A re-minted install cannot re-enter a path that already failed on that - machine.** The circuit breaker's tripped state is mirrored to the same - state file. -- **`install_predecessor_found`** on every event says whether this install's - mint found a previous install's state marker — i.e. `config.json` was lost - while `install-state.json` survived. Its true-share is the re-mint rate - directly; drift from a deliberate reset, a fresh machine, a container, or a - new user is not linkable by any local mechanism and is not counted. - -With the seed carryover, check 2's residual drift comes from the -unrecoverable buckets only — deliberate resets, fresh machines, containers, -and genuinely new users — and canary window lengths get picked from that -residual, not the raw turnover. - -## Behaviour worth knowing - -**Ramping is inclusive.** Widening `10 → 25` keeps everyone who was already -in the 10. Cohorts never reshuffle, so a before/after comparison stays valid -across a ramp. - -**Slices are independent per feature.** The bucket hashes `feature:seed`, -not the seed alone — two canaries at 10% select two different 10%s. If -they shared a slice, one unlucky cohort would receive every experiment at -once and no two rollouts could be read apart. - -**Cohorts are keyed to the install directory, not to `config.json`.** The -bucketing unit is a dedicated seed in `install-state.json`, inherited across -`config.json` re-mints (see the calibration section) — distinct from the -telemetry id and never emitted. It does not outlive `~/.hyperframes`. - -**A CLI-launched Studio adopts the CLI's decisions rather than re-deriving -them.** The CLI publishes `window.__HF_CLI_CANARY_DECISIONS` — a -`{ name: { enabled, forced } }` map. Re-deriving cannot agree in the cases -that matter: telemetry off (the CLI resolves `telemetry_opt_out`, but Studio's -opt-out is a separate localStorage flag it cannot see), an `HF_CANARY_*` -override (env vars never cross into the browser), or no seed injected (Studio -falls back to a different unit, so a different bucket). One render spanning -both surfaces must not run half-enrolled. - -`forced` carries the provenance, and the precedence follows from it — highest -first: - -1. A **forced** CLI decision (`HF_CANARY_*`). Wins outright, including over - this profile's opt-out, exactly as a local URL override does. -2. A local `?hf_canary_*=` override, same reasoning. -3. **This profile's telemetry opt-out.** Checked before any percentage - decision: the two surfaces have independent opt-outs, and CLI telemetry - being on says nothing about whether this browser profile agreed to be - measured. A cohort roll must never enrol an opted-out profile. -4. The CLI's percentage decision. -5. Local evaluation (standalone Studio, or a canary the CLI did not publish). - -Identity is treated differently from decisions. `__HF_CLI_DISTINCT_ID` and -`__HF_CLI_BUCKET_SEED` are injected only for a `Host` this server can vouch -for — a page that rebinds its hostname to `127.0.0.1` would otherwise read -them as same-origin. That means loopback by default, and on an explicit LAN -bind (`HYPERFRAMES_PREVIEW_HOST=0.0.0.0`) a `Host` naming an address or -hostname this machine actually answers on. Setting the variable does not -disable the check; a hostile `Host` is refused in either mode. - -The decisions map is not identifying, so it is published regardless, which -keeps a LAN preview in agreement with the CLI instead of silently -re-deriving. - -The decisions map is published even when telemetry is off — that is the case -it exists for. It is safe to expose where the seed is not: booleans about -features, not the value cohorts are derived from. Studio still evaluates -locally when opened standalone, or for any canary the CLI did not publish. - -## Removing your canary state - -Both `config.json` and `install-state.json` live in `~/.hyperframes`, so: +Cohorts bucket on a seed in `install-state.json`, which sits beside +`config.json` in `~/.hyperframes` — not on the telemetry id. So a full reset is +one command: ```bash rm -rf ~/.hyperframes # clears telemetry id, canary cohorts, and breaker state @@ -282,48 +84,24 @@ rm -rf ~/.hyperframes # clears telemetry id, canary cohorts, and breaker stat `hyperframes telemetry status` prints both paths if you want to inspect or delete them individually. Nothing canary-related is stored anywhere else. -**Opting out of telemetry opts you out of canaries.** A canary is a *measured* -rollout — we enrol a slice precisely so it can be compared against everyone -else. An install that sends nothing can't be compared, so enrolling it buys no -signal and only changes that user's code path, on an experimental feature, -without their knowledge. Every opt-out route counts: the persisted preference -(`hyperframes telemetry disable`), the runtime env vars -(`HYPERFRAMES_NO_TELEMETRY`, `DO_NOT_TRACK`), dev/telemetry-disabled builds, -and Studio's `hyperframes-studio:telemetryDisabled`. The decision resolves to -`telemetry_opt_out` *before* bucketing, so no cohort is assigned at all. - -An explicit `HF_CANARY_` (or `?hf_canary_=` in Studio) -override still wins — that is a deliberate local choice, and it stays the way -to exercise a canary with telemetry off. - -**It fails closed below 100%.** No install id, an unregistered name, or a CI -machine all resolve to *not enrolled*. A canary exists to bound blast radius, -so "we don't know who this is" must never mean "enrol everyone". CI is -excluded because its config is regenerated per run, so its ids are ephemeral -and would hop cohorts between runs — an explicit override still reaches it, -which is how you test a canary in CI. - -At exactly 100% those exclusions stop applying, deliberately. 100% is the step -before deleting the entry and the guard, so anything still resolving false -there would take the new path for the FIRST time at deletion, unstaged — and -CI and seedless installs are precisely the populations a dashboard cannot see, -so "100% and holding" would look green while they were never exercised. - -**Decisions are stable and memoized.** The same install always resolves the -same way, and the answer is fixed for the life of a process — a render that -starts enrolled finishes enrolled, and its telemetry agrees with what ran. - -**Do not rename a live canary.** The name is part of the hash, so renaming -reshuffles the cohort mid-rollout and invalidates the comparison. - ## Where it lives | File | Role | | --- | --- | -| `packages/core/src/canary.ts` | Pure evaluator — no fs, no network, browser-safe | | `packages/core/src/canaryRegistry.ts` | Every rollout, with owner and sunset date | -| `packages/cli/src/telemetry/canary.ts` | CLI binding: install id, env override, CI detection | +| `packages/core/src/canary.ts` | Pure evaluator — no fs, no network, browser-safe | +| `packages/cli/src/telemetry/canary.ts` | CLI binding: bucket seed, env override, CI detection | +| `packages/studio/src/telemetry/canary.ts` | Studio binding: adopts the CLI's published decisions | -The evaluator is deliberately dependency-free so studio and the embeddable -player can use it too; those surfaces need their own thin binding to supply an -id, since only the CLI has `anonymousId`. +The evaluator is dependency-free so Studio and the embeddable player can use it +too; each surface supplies its own unit id through a thin binding. Studio +adopts the CLI's decisions rather than re-deriving them, so one render spanning +both surfaces never runs half-enrolled. + +## Related topics + +- [Testing local changes](/contributing/testing-local-changes) — exercise your + canary before anyone else gets it. +- [Release channels](/contributing/release-channels) — which branch a ramp belongs on. +- [`telemetry` command](/packages/cli#telemetry) — what is collected, and how a + user turns it off. diff --git a/docs/custom.css b/docs/custom.css index b0b3b147f..96be8fede 100644 --- a/docs/custom.css +++ b/docs/custom.css @@ -182,6 +182,16 @@ h3 { object-fit: cover; pointer-events: none; } +/* A route with no preview clip: same box, no black rectangle. */ +.hf-workflow-route-noclip { + display: block; + width: 100%; + aspect-ratio: 16 / 9; + margin: 0; + border-radius: 0.5rem; + background: color-mix(in srgb, currentColor 8%, transparent); +} + .hf-workflow-route-title { display: block; diff --git a/docs/docs.json b/docs/docs.json index 1f565669a..fbe7cfecf 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -173,7 +173,7 @@ "guides/music-to-video", "guides/slideshow", "guides/general-video", - "guides/export-and-share" + "guides/hyperframes-vs-remotion" ] }, { @@ -186,7 +186,8 @@ "guides/voice-and-audio", "guides/remove-background", "guides/color-grading", - "guides/media-effects" + "guides/media-effects", + "guides/export-and-share" ] }, { @@ -530,7 +531,6 @@ "concepts/frame-adapters", "concepts/determinism", "guides/html-in-canvas", - "guides/hyperframes-vs-remotion", "guides/figma" ] }, diff --git a/docs/guides/design-tools.mdx b/docs/guides/design-tools.mdx index 0d0c266ea..96da83cc5 100644 --- a/docs/guides/design-tools.mdx +++ b/docs/guides/design-tools.mdx @@ -71,7 +71,7 @@ These settle layout, palette, type, and scene direction first. 3. Save it to disk, then open that folder with a coding agent. 4. Let the agent check timing, motion, media, captions, and rendering. -[Claude Design instruction](https://github.com/heygen-com/hyperframes/blob/main/docs/guides/claude-design-hyperframes.md) · [Open Design handoff](https://github.com/heygen-com/hyperframes/blob/main/docs/guides/open-design-hyperframes.md) +[Claude Design instruction](https://github.com/heygen-com/hyperframes/blob/main/docs/guides/design-tools-hyperframes.md) · [Open Design handoff](https://github.com/heygen-com/hyperframes/blob/main/docs/guides/open-design-hyperframes.md) ## Is the handoff any good? diff --git a/docs/prompting/captions-and-talking-heads.mdx b/docs/prompting/captions-and-talking-heads.mdx index 33e582311..412615a61 100644 --- a/docs/prompting/captions-and-talking-heads.mdx +++ b/docs/prompting/captions-and-talking-heads.mdx @@ -99,4 +99,6 @@ What you can already steer from the prompt, before you've learned any technique. For the beat-timestamped skeleton these prompts share, see [Prompt anatomy](/prompting/anatomy); for adjectives that map to motion and emphasis settings, [Vocabulary](/prompting/vocabulary). To build a video from scratch instead of dressing existing footage, start at the router in `/hyperframes`. +The workflow this level rides is documented at [Captions and talking head](/guides/captions-and-recuts) — what it takes as input, what it asks you before it builds, and what it returns. + *Next: [Music videos and slideshows](/prompting/music-and-slideshows) — swap footage for a soundtrack, or slides, and let the beat or the deck set the pace.* diff --git a/docs/prompting/code-and-prs.mdx b/docs/prompting/code-and-prs.mdx index 7da9af3b9..51298889b 100644 --- a/docs/prompting/code-and-prs.mdx +++ b/docs/prompting/code-and-prs.mdx @@ -93,4 +93,6 @@ What you can already steer from the prompt, before you've learned any technique. - ❌ `a 40-second narrated walkthrough` - ✅ `a ~40-second narrated walkthrough` +The workflow this level rides is documented at [PR to video](/guides/pr-to-video) — what it takes as input, what it asks you before it builds, and what it returns. + *Next: [Captions and talking-head footage](/prompting/captions-and-talking-heads) — same one-prompt move, now dressing footage you already shot.* diff --git a/docs/prompting/color-grading.mdx b/docs/prompting/color-grading.mdx index b1f13428c..09982c596 100644 --- a/docs/prompting/color-grading.mdx +++ b/docs/prompting/color-grading.mdx @@ -193,7 +193,7 @@ If you composite a subject into the shot, do it **before** grading. A CRT warps /> *The footage degrades; the HUD does not. It is an overlay, composed above the media canvas.* -The HUD in that shot is not part of the grade. It is a [`camcorder-hud`](/guides/media-overlays) registry block — real HTML, CSS, and a paused GSAP timeline composed *above* the media canvas. Grading never touches it, which is exactly what you want: burn a timestamp into the source pixels and it degrades with them; put it in an overlay and it stays crisp, editable, and timeline-driven while the footage falls apart underneath. +The HUD in that shot is not part of the grade. It is a [`camcorder-hud`](/catalog) registry block — real HTML, CSS, and a paused GSAP timeline composed *above* the media canvas. Grading never touches it, which is exactly what you want: burn a timestamp into the source pixels and it degrades with them; put it in an overlay and it stays crisp, editable, and timeline-driven while the footage falls apart underneath. ## Animating a grade diff --git a/docs/prompting/design-systems.mdx b/docs/prompting/design-systems.mdx index 6168dd730..2f1c34554 100644 --- a/docs/prompting/design-systems.mdx +++ b/docs/prompting/design-systems.mdx @@ -115,7 +115,7 @@ Restyling scene by scene afterward pulls threads out of a design that was balanc How pinning exact hexes and type direction removes drift. - + Attach a brand guide or screenshot to seed a first draft from your look. diff --git a/docs/prompting/explainers.mdx b/docs/prompting/explainers.mdx index 778bba830..c5c167181 100644 --- a/docs/prompting/explainers.mdx +++ b/docs/prompting/explainers.mdx @@ -137,4 +137,6 @@ the preset picks the palette. If you have colors, name them. - ❌ `make it look on-brand` - ✅ `brand color #FF5533 on off-black` +The workflow this level rides is documented at [Faceless explainer](/guides/faceless-explainer) — what it takes as input, what it asks you before it builds, and what it returns. + *Next: [Code changes and PRs](/prompting/code-and-prs) — point a workflow at a merged GitHub PR instead of a blank page.* diff --git a/docs/prompting/motion-graphics.mdx b/docs/prompting/motion-graphics.mdx index f9c2236c8..d3952660c 100644 --- a/docs/prompting/motion-graphics.mdx +++ b/docs/prompting/motion-graphics.mdx @@ -86,4 +86,6 @@ Each reuses a registry block, so the agent composes rather than hand-building fr For the six-part skeleton and the per-beat content formula these prompts share, see [Prompt anatomy](/prompting/anatomy); for the full set of run-verified examples, [Verified examples](/prompting/examples). Unsure whether your ask is a motion graphic at all? Start at the router in `/hyperframes`. +The workflow this level rides is documented at [Motion graphics](/guides/motion-graphics) — what it takes as input, what it asks you before it builds, and what it returns. + *Next: [Prompt anatomy](/prompting/anatomy) — you've been riding workflows through six one-prompt inputs; Level 2 opens the prompt itself.* diff --git a/docs/prompting/music-and-slideshows.mdx b/docs/prompting/music-and-slideshows.mdx index 34d485443..d34d1b79c 100644 --- a/docs/prompting/music-and-slideshows.mdx +++ b/docs/prompting/music-and-slideshows.mdx @@ -101,4 +101,6 @@ This is the clause in the [full capstone prompt](/prompting/capstone#the-prompt- /> *That clause, rendered — the region cut from the finished film.* +The workflow this level rides is documented at [Music to video](/guides/music-to-video) — what it takes as input, what it asks you before it builds, and what it returns. + *Next: [Motion graphics](/prompting/motion-graphics) — the shortest one yet, a single motion graphic where motion alone is the message.* diff --git a/docs/prompting/overview.mdx b/docs/prompting/overview.mdx index b413c2e1c..e5675ca1c 100644 --- a/docs/prompting/overview.mdx +++ b/docs/prompting/overview.mdx @@ -79,7 +79,7 @@ The installer shows a picker. Select the **core skills** below — every project ## Claude Design -Claude Design uses a different setup. Download [`claude-design-hyperframes.md`](https://github.com/heygen-com/hyperframes/blob/main/docs/guides/claude-design-hyperframes.md) from GitHub (click the ↓ button), then **attach it to your chat** (don't paste the URL — file attachments produce better output): +Claude Design uses a different setup. Download [`claude-design-hyperframes.md`](https://github.com/heygen-com/hyperframes/blob/main/docs/guides/design-tools-hyperframes.md) from GitHub (click the ↓ button), then **attach it to your chat** (don't paste the URL — file attachments produce better output): ```text Use the attached skill. 25-second LinkedIn video for my startup. @@ -90,7 +90,7 @@ Traction: 200+ teams, $1.2M ARR, 18% MoM growth. CTA: autocrmhq.com ``` -Claude Design produces a valid first draft (brand identity, scene content, animations, transitions). Download the ZIP and refine in any AI coding agent with `npx hyperframes preview` running. See the [Claude Design guide](/guides/claude-design) for the full workflow. +Claude Design produces a valid first draft (brand identity, scene content, animations, transitions). Download the ZIP and refine in any AI coding agent with `npx hyperframes preview` running. See the [Claude Design guide](/guides/design-tools) for the full workflow. diff --git a/docs/prompting/product-launch.mdx b/docs/prompting/product-launch.mdx index f28dee125..32ad3d11d 100644 --- a/docs/prompting/product-launch.mdx +++ b/docs/prompting/product-launch.mdx @@ -34,7 +34,7 @@ A launch or promo that *sells*: SaaS promos, feature reveals, product demos, app | You want… | Route | | --- | --- | | To market, launch, promote, or reveal a product (the default for any commercial URL) | `/product-launch-video` | -| A video *of* a general site — a portfolio / blog / docs / landing-page tour or showcase, not a sales pitch | `/product-launch-video` too — say *tour* or *showcase* in the brief (see the [website-to-video guide](/guides/website-to-video)) | +| A video *of* a general site — a portfolio / blog / docs / landing-page tour or showcase, not a sales pitch | `/product-launch-video` too — say *tour* or *showcase* in the brief (see the [website-to-video guide](/guides/product-launch-video)) | Both route to the same workflow now; what changes is the brief. "Promo for our site" is a launch — sell it. A neutral walkthrough of a docs site is a tour — say so, and the workflow shows the site's own captured screens instead of pitching. Unsure → start at `/hyperframes` and let it route. diff --git a/docs/snippets/workflow-chooser.jsx b/docs/snippets/workflow-chooser.jsx index cb8dc3e3a..14c981dcf 100644 --- a/docs/snippets/workflow-chooser.jsx +++ b/docs/snippets/workflow-chooser.jsx @@ -66,6 +66,11 @@ export const WorkflowChooser = () => { video: `${CDN}/wfv2-general.mp4`, poster: `${CDN}/wfv2-general.jpg`, }, + { + title: "Port a Remotion composition", + bring: "Bring an existing Remotion project. One-way migration, not a new build.", + href: "/guides/hyperframes-vs-remotion", + }, ]; // Lazy initializer, not a post-mount effect: with useState(false) the first @@ -110,16 +115,23 @@ export const WorkflowChooser = () => { aria-label={`${route.title}. ${route.bring}`} className="hf-workflow-route" > -