, or HomeHow We Built a Cross-Runtime Engine Catalog That Doesn’t Break
Vivid engine catalog across React, Tauri, and Python
How We Built a Cross-Runtime Engine Catalog That Doesn’t BreakPublished Mar 21, 2026 · Updated Mar 21, 2026One JSON catalog, three runtimes—how Vivid keeps the React app, Tauri backend, and Python inference aligned so jobs don’t drift.

When we say Vivid is a large codebase, we mean it: a desktop app, a Rust backend, Python inference, cloud runtimes, and shared contracts tying them together. One of the hardest problems was not “run a model”—it was making every layer agree on what running a model means.

The React renderer, the Tauri backend, and the Python runtime are three different environments. They do not naturally share types, imports, or assumptions. If each layer invents its own notion of engines, backends, and dependencies, you get configuration drift: the UI shows options the backend will reject, or the runtime discovers missing packages halfway through a job.

We solved that with a single cross-runtime engine catalog and strict consumption at each boundary.

The problem: multiple runtimes, multiple truths

Most AI apps break quietly:

  • The frontend assumes a model exposes parameters X
  • The backend validates against Y
  • The runtime crashes on Z

That is configuration drift, and it destroys reliability and debuggability.

mermaid

At a systems level, the shape of the fix is familiar:

Problem
Multiple runtimes each carry a partial copy of “truth”
GoalOne source of truth and deterministic execution
PatternCentral schema → typed boundaries → adapters, not duplicated configs

What we ship: one JSON catalog

In Vivid, the canonical definition lives in src/shared/engine_runtime_catalog.json. It is versioned (for example version: 2), carries the pinned Python runtime expectation, lists upstream repos with dependency pins, and defines an engines array.

Each engine entry describes, among other things:

  • engineId, operation, human-facing label and description
  • supportedBackends — TensorRT variants, ONNX Runtime paths (CUDA, CoreML, DirectML), OpenVINO, MIGraphX, NCNN, CPU, etc.
  • defaultBackendByPlatform — sensible defaults per OS
  • requiredPackagesByBackend and requiredUpstreamRepos
  • requiredPythonModules
  • executionMode (for example VSMLRT, hybrid, native PyTorch)
  • supportsOnnx / supportsPytorch and fallbackOrder

That is the contract: model configuration as data, not as three hand-maintained lists.

mermaid

How each layer consumes the same file

1. TypeScript (renderer)

The catalog is imported as JSON and typed in src/shared/engineRuntimeCatalog.ts. Helpers like getEngineRuntimeCatalog(), getEngineEntry(), and getRequiredPackagesForBackend() give the UI and services a single API over the same data the backend and Python use.

Compatibility logic (for example which backend strings imply NVIDIA vs Apple Silicon) still lives in code—src/renderer/services/engineCompat.ts—but it is informed by the catalog’s backend vocabulary so the UI does not fork a parallel engine list.

2. Rust (Tauri)

The backend embeds the catalog at compile time. src-tauri/src/core/engine_resolver.rs uses include_str! to load engine_runtime_catalog.json, deserializes it into EngineRuntimeEntry / EngineRuntimeCatalog, and resolves requirements such as which package IDs and upstream repos an engine_id + backend pair needs. Invalid combinations can be caught before a long-running job starts.

The same JSON is also bundled with the app via src-tauri/tauri.conf.json so the runtime path stays consistent in packaged builds.

3. Python (local inference)

src/inference/inference_impl/engine_runtime_catalog.py locates the same file (with VIVID_CATALOG_PATH override for tests or container layouts), loads it into frozen dataclasses, and exposes lookups for backend policy and dependency preflight—backend_policy.py and related code consume those definitions instead of hardcoding engine tables.

4. Cloud (Modal)

The cloud image wires the catalog into the container environment so remote runs enforce the same backend and dependency policy as local execution—see paths like VIVID_CATALOG_PATH and the shared catalog copy in src/cloud/modal_runtime/image.py.

Guardrails in the repo

Drift is not only a runtime bug; it is a process bug. The repository includes validation that keeps pins and catalog entries aligned—scripts/validate_engine_runtime_catalog.py and scripts/validate_torch_runtime_stack.py—so dependency bumps do not silently diverge from what the catalog claims.

mermaid

Early checks in CI or local dev catch catalog mistakes before they become user-facing failures.

Why this matters

Without a single catalog:

  • The UI can lie (show engines or backends that cannot run)
  • Jobs fail mid-execution with obscure import or backend errors
  • Debugging means comparing three different mental models

With one catalog and typed boundaries:

  • Jobs are much easier to reason about and reproduce
  • Validation can happen early, in the shell and in the queue
  • Adding or extending an engine is data + code in known places, not a scavenger hunt across stacks

The insight

Treat model and engine configuration like an API contract—versioned, shared, and enforced—not a suggestion each layer can reinterpret.

Building Vivid was never “just” an upscaler: it was a system that has to run locally, in the cloud, and under failure, without wasting users’ time. The engine catalog is one of the pieces that makes that claim credible.

How the layers connect

mermaid

We’re shipping soon—follow along for the rest of the story.