---
slug: cookbook/design
title: Serving cookbook design
---
<a id="serving-cookbook-design"></a>

The cookbook publishes deployment catalogs and a reusable JavaScript API so
different UIs can share the same configuration logic. Native serving examples
provide the starting values; authored JSON Schemas describe editable fields.
The browser applies explicit edits and generates YAML and launch instructions.

Recipe syntax, schema overrides, supported runtimes, build commands and tests
belong in the [contributor guide](/FastVideo/contributing/cookbook_configuration).
This page defines the data flow, public API and configuration guarantees.

## Sources and delivery {#sources-and-delivery}

```text
Native serving YAML + option schemas + deployment manifests
                         |
              build-cookbook-config.mjs
                         |
               Generated JSON catalogs
                         |
                 Blume / static hosting
                         |
            cookbook-config.js + UI edits
                         |
                 YAML and command strings
```

| Source | Responsibility |
| --- | --- |
| `examples/serving/*.yaml` | Complete explicit baseline, including hidden settings |
| `docs/cookbook/options.yaml` | Authored field schemas and runtime metadata |
| `docs/cookbook/recipes/*.yaml` | Deployments, baseline references, selected fields and schema overrides |
| `docs/js/build-cookbook-config.mjs` | Validate metadata and export static catalogs |
| `docs/js/cookbook-config.mjs` | Load catalogs, preview fields, validate edits and produce output |

Catalog generation runs in Node without importing FastVideo or loading model
weights. The docs build generates assets before Blume copies them into the
published site. Generated JSON, the combined API/validator bundle and its license notices
are Git-ignored build output published together under `assets/cookbook-config/`.
Website visitors need only the static assets. The schemas are author-maintained
and must stay aligned with native runtime behavior.

## Catalog contract {#catalog-contract}

The builder writes a small index and one catalog per deployment:

```text
docs/assets/cookbook-config/cookbook-config.js
docs/assets/cookbook-config/cookbook-config.LICENSE.txt
docs/assets/cookbook-config/index.json
docs/assets/cookbook-config/recipes/<model-key>/<deployment-key>.json
```

The index has no configurations or field schemas:

```text
models: [{
  id, title, model_id,
  deployments: [{id, label, workload, runtime, catalog_url}]
}]
```

Each deployment catalog contains `id`, `title`, `summary`, `model`, `deployment`,
`workload`, `runtime`, `source_config`, `env`, `requirements`, optional `guide`,
the complete `base_config`, and ordered `controls: [{path, schema}]`.
Controls use canonical paths such as `server.port`; their schemas are JSON
Schema fragments that a UI can render using its own widgets.

The browser fetches only the selected deployment. `loadDeployment()` resolves
relative catalog URLs against `index.url` but returns stored metadata links
without rewriting them. The UI resolves `guide.url` and
`runtime.client_guide_url` against the published index URL. Guides are links
to documentation, not embedded HTML.

## Shared JavaScript API {#shared-javascript-api}

`docs/js/cookbook-config.mjs` exports the recipe, capacity, and assessment
helpers below. The generated `assets/cookbook-config/cookbook-config.js` bundles
them with Ajv and exposes the browser global `FastVideoConfigCookbook` and
CommonJS exports:

| Function | Result |
| --- | --- |
| `loadIndex(url, {signal, fetcher} = {})` | Promise of `{models, url}`; URL context for catalog links |
| `loadDeployment(index, id, {signal, fetcher} = {})` | Promise of the selected complete catalog |
| `getOptions(catalog, config = catalog.base_config, edits = {})` | `[{path, schema, value}]`, including GPU-dependent degree limits |
| `resolveConfig(catalog, edits = {})` | `config`, `yaml`, `argv`, `command`, `clientRequest`, `clientCommand`, optional `websocketUrl` |
| `sampleRequest(metadata, config)` | `{body, command}` and optional `websocketUrl` for a native serving baseline |
| `WORKLOADS` | Frozen `t2v`/`i2v`/`t2i`/`t2a`/`v2a` input/output/endpoint/media metadata used by the builder and sample client |
| `estimateMemory({config, workload, model, hardware, memoryBudgetGiB, partitionId, hostMemoryGb, headroom})` | Analytical one-device estimate with separate device and host budgets |
| `assessCapacity({model, example, hardware, config, request, env, revisions, ...})` | `{status, basis, analytical, evidence, compatibility, notes}` combining analysis and applicable evidence |
| `matchEvidence({model, example, config, request, env, hardware, revisions})` | `{applicable, unverified, rejected}` measured runs |
| `recommendCapacity({models, hardware, task, request, env, revisions, limit})` | Candidates with model/example, assessment, reasons, and lower-memory alternatives; unknown remains explicit |
| `resolveExecution({model, config, env})` | Effective topology, offload, precision, attention, and unsupported switches |
| `loadCapacityIndex(url, options)` | Promise of the model-summary index and resolved source URL |
| `loadCapacityModel(index, id, options)` | Promise of one expanded model, examples, and reference runs |
| `loadCapacityHardware(index, options)` | Promise of `{version, devices, url}` for the source-backed hardware lookup |

`sampleRequest()` is also used by model pages backed by a checked-in serving
YAML rather than a full editable catalog. Its metadata supplies `model.id`,
`workload`, and `runtime.interface`/`runtime.server_defaults`. It builds client
instructions only; it does not validate the configuration or run a request.
The shared workload map selects the canonical REST endpoint and output
extension; it does not establish that a model supports that workload.

For WebSocket deployments, `clientRequest` is `null` and `websocketUrl` is
present. REST deployments return a request object and omit `websocketUrl`.

`signal` supports canceling obsolete loads; `fetcher` accepts a fetch-compatible
replacement for tests or other callers. Loading failures reject the promise.
Loading checks the consumed index/catalog structure, including unique model,
deployment and control identities. Malformed data fails before reaching UI
helpers. Relative catalog URLs are supported; these checks do not validate
full native configurations or certify runtime compatibility.

Load one bundle before calling the API. Ajv is included; no separate validator
script or CDN is needed. For this site's deployment prefix:

```html

```

```javascript
const api = FastVideoConfigCookbook;
const index = await api.loadIndex("/FastVideo/assets/cookbook-config/index.json");
const catalog = await api.loadDeployment(index, "fastwan21/cuda-rest");
const edits = {"server.port": 9000};
const fields = api.getOptions(catalog, catalog.base_config, edits);
const result = api.resolveConfig(catalog, edits);
// Render fields; display result.yaml/result.command and offer a YAML download.
```

Adjust asset URLs for other deployment prefixes. Node tools can import the
handwritten ES module directly; they do not require a generated bundle.
`getOptions()` previews pending edits without
full schema/topology validation; `resolveConfig()` validates before generating
output. Edits are a flat path-to-value object with correctly typed JavaScript
values, and only declared controls are editable.

The core returns data and strings. The UI owns layout, widgets, edit state,
input parsing, loading/error states, cancellation, stale-response handling,
guide links, copying and downloads. Catch failures and clear invalid output.
Reuse the loaded catalog and treat it as read-only: validators are cached by
schema object identity. Returned field previews and configurations are copies.

## Configuration invariants {#configuration-invariants}

```text
Displayed values = baseline + edits; missing fields show Inherited
Saved YAML       = complete explicit baseline + edits
Reset            = resolveConfig(catalog, {})
```

- `schema.default` is informational. A field value of `undefined` remains
  omitted/inherited; validation never inserts schema defaults.
- Explicit `false`, `0` and `null` retain their meanings. Missing and null differ.
- Resolution works on a copy. Hidden settings and sibling fields survive edits;
  arrays replace whole values. YAML formatting and comments need not survive.
- Removing an edit restores baseline behavior; it does not delete a baseline
  setting. Changing deployments requires the UI to reset its edit state.
- Field validation uses authored schemas. Topology checks enforce positive GPU
  counts and parallel degrees that divide the count, with supported `-1`
  automatic values. Invalid combinations are rejected without changing edits.

The native runtime still resolves model-, hardware- and request-dependent
defaults. Cookbook validation does not establish complete native validity,
server readiness or GPU memory fit. Client instructions use same-machine
addresses: REST deployments return a sample request command, while streaming
deployments return a health command and WebSocket URL. The UI displays these
instructions; the API does not execute them.

## Validation errors {#validation-errors}

`CookbookValidationError` is an additional named export and browser-global member.
It extends `Error`, so existing `catch (error) { ...error.message }` handlers work.

| Property | Meaning |
| --- | --- |
| `message` | Human-readable explanation; do not parse it for field identity |
| `path` | Canonical selected field or topology path, such as `server.port`; `null` for configuration-wide failures |
| `errors` | Detached records containing `instancePath`, `schemaPath`, `keyword`, `params` and `message` |

For field-schema failures, `errors` preserves Ajv details. `instancePath` is a
JSON Pointer **relative to the selected field's value**: for an object control
at `generator.pipeline.experimental.settings`, `/tags/0` points inside that
object. Missing/additional property names remain in `params`. Non-Ajv failures
use `editable`, `path`, `topology` or `configuration` as their keyword;
`instancePath` and `schemaPath` are empty. A topology failure may include
`params.relatedPaths`. HTTP, JSON parsing and cancellation failures remain
ordinary loading errors. The error records are copied, so later validations
cannot overwrite details already shown by the UI.

```javascript
try {
  const result = api.resolveConfig(catalog, edits);
} catch (error) {
  if (error instanceof api.CookbookValidationError) {
    highlightField(error.path, error.errors);
  }
  showError(error.message);
}
```

## Validation boundaries and future work {#validation-boundaries-and-future-work}

The Node builder and browser validate individual selected fields with Ajv and
apply the existing GPU/parallel-degree checks. Hidden baseline fields are
preserved, not exhaustively validated. Native path/type drift checks run
separately in an existing FastVideo Python environment; they are not a Python
dependency of the docs build. See the contributor guide for the command and
its coverage limits.

TODO: consider reusable deployment-wide validation only when a maintained
recipe needs it. It is not implemented in this change:

- An offset frame grid such as `(frames - 1) % 4 === 0` is not `multipleOf: 4`.
  A bounded enum or reusable step/offset rule could express it. Some Wan paths
  align frames rather than reject them, so exact-output policy must be labeled.
- H3's `width * height &lt;= 768 * 1344` requires a cross-field arithmetic check.
  Separate per-dimension bounds cannot enforce it.
- Refinement-dependent geometry could use JSON Schema `if`/`then`/`else` on a
  complete configuration object. The current field-only validator cannot see
  sibling fields. The current LTX2 baseline fixes refinement on and uses 64-pixel
  dimensions accordingly.

The [capacity metadata catalog](/FastVideo/contributing/capacity_estimation) supplies
shared hardware/component facts and optional recorded runs through separate
static loaders. Optional `capacity` sections extend existing model manifests;
model identity and example configurations are derived from their deployments
and native baseline YAML. `estimateMemory()` is analytical and never verifies a
recipe. `assessCapacity()` keeps analytical fit, measured device peaks, and
applicable evidence distinct; allocator-only peaks and successful generations
do not establish device fit or a minimum-VRAM requirement. The hardware asset is
versioned and source-backed; the UI owns catalog search and the custom-device
form, while the shared API owns lookup, normalization, and estimation. No general
arithmetic validator or CLI override workflow is introduced here.

## Cookbook interface

Family and model pages use the React cookbook in `docs-site/`. The model inventory
comes from `docs/assets/cookbook-recipes.json`; the shared configuration API
continues to own editable serving recipes. The old family JavaScript selector
and site-theme assets have been removed.

<a id="coexistence-with-the-current-cookbook"></a>