> ## Documentation Index
> Fetch the complete documentation index at: https://hyperframes-codex-docs-human-first-refactor.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# HTML schema reference

> The current contract for a HyperFrames composition.

HyperFrames uses normal HTML and CSS for appearance. A small set of attributes
declares the frame size, duration, clips, media, and nested compositions.

For a gentler explanation, start with [Compositions](/concepts/compositions) and
[Data attributes](/concepts/data-attributes).

## Minimal composition

```html theme={null}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=1920, height=1080" />
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
    <style>
      body { margin: 0; }
      #root {
        position: relative;
        width: 1920px;
        height: 1080px;
        overflow: hidden;
      }
      .clip {
        position: absolute;
        inset: 0;
        display: grid;
        place-items: center;
      }
    </style>
  </head>
  <body>
    <div
      id="root"
      data-composition-id="main"
      data-start="0"
      data-duration="5"
      data-width="1920"
      data-height="1080"
    >
      <section
        id="title-card"
        class="clip"
        data-start="0"
        data-duration="5"
        data-track-index="1"
      >
        <h1 id="title">Hello HyperFrames</h1>
      </section>
    </div>

    <script>
      window.__timelines = window.__timelines || {};
      const timeline = gsap.timeline({ paused: true });
      timeline.fromTo(
        "#title",
        { y: 48, opacity: 0 },
        { y: 0, opacity: 1, duration: 0.6, ease: "power3.out" },
        0.2,
      );
      window.__timelines.main = timeline;
    </script>
  </body>
</html>
```

The root is a real, explicitly sized box. Its `data-composition-id` matches the
timeline registry key.

## Composition root

| Attribute                      | Required                             | Meaning                                      |
| ------------------------------ | ------------------------------------ | -------------------------------------------- |
| `data-composition-id`          | Yes                                  | Unique composition ID                        |
| `data-start="0"`               | Yes on the top-level root            | Start of the composition                     |
| `data-width` and `data-height` | Yes                                  | Authored frame dimensions in pixels          |
| `data-duration`                | Usually                              | Total render duration in seconds             |
| `data-no-timeline`             | Only for a timeline-free composition | Tells the runtime not to wait for a timeline |

An explicit root `data-duration` is the render length. The compiler reads it
before composition scripts run, so a script or variable override cannot change
that value for the same render.

The root may omit `data-duration` only when HyperFrames can infer a finite
duration from the registered animation runtime or timed media. Three.js,
unbounded animation, and timeline-free compositions need an explicit duration.

## Timed clips

| Attribute          | Required                                         | Meaning                                              |
| ------------------ | ------------------------------------------------ | ---------------------------------------------------- |
| `id`               | Yes                                              | Stable identifier for timing, editing, and animation |
| `data-start`       | Yes                                              | Start in seconds or a relative timing expression     |
| `data-duration`    | Yes for DOM, image, and nested-composition clips | Visible slot length in seconds                       |
| `data-track-index` | Yes                                              | Timeline lane used to prevent temporal overlap       |
| `class="clip"`     | Yes for authored timed DOM and image elements    | Lets the runtime own their visibility window         |

`data-track-index` does not control paint order. Use CSS `z-index` for
front-to-back layering. Two clips on the same track must not overlap in time.

Video visibility is managed as media and does not require `class="clip"`.
Audio has no visual lifecycle.

## Media

```html theme={null}
<video
  id="demo"
  src="./assets/demo.mp4"
  data-start="0"
  data-duration="8"
  data-track-index="0"
  muted
  playsinline
></video>
```

| Attribute               | Applies to                       | Meaning                                              |
| ----------------------- | -------------------------------- | ---------------------------------------------------- |
| `data-media-start`      | Video and audio                  | Offset into the source file                          |
| `data-playback-start`   | Video, audio, nested composition | Source-time offset used by trim and split operations |
| `data-playback-rate`    | Video, audio, nested composition | Playback multiplier from `0.1` to `5`                |
| `data-volume`           | Video and audio                  | Static volume from `0` to `1`                        |
| `data-has-audio="true"` | Video                            | Declares that the video contributes audio            |

Video and audio may omit `data-duration` when their intrinsic duration is known
and the whole remaining source should play.

Do not imperatively call `play()`, `pause()`, or set `currentTime`.
HyperFrames owns media playback and seeking. A video should be `muted` unless it
is intentionally audible and declares `data-has-audio="true"`.

Media can live inside nested composition markup. Keep element IDs unique across
the assembled project because render-time frame injection targets those IDs.

## Color grading and media effects

Studio and the CLI store color correction, grading, finishing controls, LUTs,
and media effects on an image or video with `data-color-grading`:

```html theme={null}
<video
  id="demo"
  src="./assets/demo.mp4"
  data-color-grading='{
    "preset": "clean-studio",
    "intensity": 0.8,
    "adjust": { "highlights": -0.08, "shadows": 0.06 },
    "details": { "grain": 0.12, "vignette": 0.08 },
    "effects": { "bloom": 0.12 },
    "colorSpace": "rec709"
  }'
></video>
```

The current effect families include essentials, retro and glitch, print, and
art treatments. Run
`npx hyperframes media-treatment --capabilities --json` for the current
machine-readable surface instead of hard-coding an old effect list.

The grading pipeline applies to real `<img>` and `<video>` elements. It does
not grade a complete HTML scene. Use Studio or
[`media-treatment`](/packages/cli#media-treatment) for normal authoring; see
[Color Grading](/guides/color-grading) and [Media Effects](/guides/media-effects)
for the workflow and current SDR/HDR boundary.

## Relative timing

A non-numeric `data-start` refers to the end of another clip in the same
composition:

```html theme={null}
<video
  id="intro"
  data-start="0"
  data-duration="4"
  data-track-index="0"
  src="./intro.mp4"
  muted
  playsinline
></video>

<section
  id="result"
  class="clip"
  data-start="intro + 0.5"
  data-duration="3"
  data-track-index="0"
>
  Result
</section>
```

Supported forms are `clip-id`, `clip-id + seconds`, and
`clip-id - seconds`. References stay within one composition, must resolve to a
known duration, and cannot form a cycle. Put intentional overlaps on different
tracks.

## Nested compositions

The host declares a fixed timeline window:

```html theme={null}
<div
  id="pricing-scene"
  data-composition-id="pricing"
  data-composition-src="./compositions/pricing.html"
  data-start="4"
  data-duration="6"
  data-track-index="1"
  data-width="1920"
  data-height="1080"
></div>
```

The host `data-composition-id` must match the ID inside the source file and its
timeline registry key. The host `data-duration` controls how long the nested
composition remains visible. A shorter inner timeline holds its final state;
a shorter host duration cuts the slot.

A nested composition file transports its live markup through `<template>`.
Styles and scripts needed by that composition must be inside the template:

```html theme={null}
<template>
  <style>
    #root {
      position: absolute;
      inset: 0;
    }
  </style>

  <div
    id="root"
    data-composition-id="pricing"
    data-width="1920"
    data-height="1080"
  >
    <!-- scene content -->
  </div>

  <script>
    window.__timelines = window.__timelines || {};
    const timeline = gsap.timeline({ paused: true });
    // scene animation
    window.__timelines.pricing = timeline;
  </script>
</template>
```

HyperFrames seeks nested timelines independently. Do not add a child timeline
manually to the parent GSAP timeline.

## Variables

Declare the schema with `data-composition-variables`, then pass values through a
render or a nested host:

```html theme={null}
<html
  data-composition-variables='[
    {"id":"title","type":"string","label":"Title","default":"Hello"}
  ]'
>
```

```html theme={null}
<div
  data-composition-id="pricing"
  data-composition-src="./compositions/pricing.html"
  data-variable-values='{"title":"Built for teams"}'
  data-start="0"
  data-duration="6"
  data-track-index="1"
  data-width="1920"
  data-height="1080"
></div>
```

Use `data-var-text`, `data-var-src`, or CSS `var(--variableId)` for direct
bindings. Use `getVariables()` when the value affects logic.

## Animation contract

A composition using GSAP must:

* create one finite timeline with `{ paused: true }`;
* register it synchronously on `window.__timelines`;
* use the same key as `data-composition-id`;
* avoid wall-clock state, unseeded randomness, and infinite repeats.

HyperFrames controls seeking. Composition code describes how the visual state
looks at a given time.

## Validate

```bash theme={null}
npx hyperframes lint
npx hyperframes check
```

`lint` checks the static contract. `check` opens the project in a browser and
checks runtime behavior, layout, motion, and contrast. Watch representative
snapshots and the finished render as the final visual gate.
