> ## Documentation Index
> Fetch the complete documentation index at: https://substrate.docs.unknowncreatives.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Runtime & Imports: Wiring Your App to Substrate

> The required wiring for every web integration: three public import aliases with an engine-swap guarantee, the three-call runtime sequence that drives the solver, and the OS preference helpers.

**Every web integration must do what's on this page.** Substrate solves color at runtime, so an app that skips the wiring here renders no solved values at all. The full picture is three required pieces and one situational one:

| Step                                                        | Necessity                                                                                                 | Where                                   |
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------- |
| Import through the three public aliases                     | Required                                                                                                  | This page                               |
| Load the CSS barrel + initialize the runtime                | Required — **written for you by `substrate setup`**; one import and one call by hand on the vendored path | This page                               |
| Opt elements into the cascade with `data-ucs` / `data-mode` | Required                                                                                                  | [Markup Opt-In](/markup)                |
| Scope nested surfaces with the Surface component            | Required when surfaces nest                                                                               | [Surface Component](/surface-component) |
| Follow OS preferences with the runtime helpers              | Recommended                                                                                               | This page                               |

For the setup steps that get Substrate into your repo in the first place — vendoring the engine, running `substrate init`, wiring bundler configs — see the [Quickstart](/quickstart).

***

## The three public aliases

Client code imports Substrate through exactly three aliases. This is the entire import contract:

| Alias                     | Resolves to                     | Use it for                                                 |
| ------------------------- | ------------------------------- | ---------------------------------------------------------- |
| `@substrate/engine`       | `substrate/engine/src/index.ts` | The runtime engine API — solver, sync functions, types     |
| `@substrate/components/*` | `substrate/components/*`        | Client-owned components (`Surface`, catalog entries)       |
| `@substrate/generated/*`  | `substrate/generated/*`         | Pipeline output — generated CSS, registries, intermediates |

<Note>
  **The engine-swap guarantee.** These three specifiers are the supported client API, and swapping the engine underneath never changes your import statements. A verified sealed-engine setup resolves `@substrate/engine` to a prebuilt runtime bundle rather than to source, using the same specifier — so the application never holds a path into engine internals.
</Note>

`substrate init` writes the aliases into `tsconfig.json` automatically and prints the block for bundler and test configs, which it won't edit because they're arbitrary code. Re-print them any time with `substrate init --report-aliases`.

### What is not a client path

Two patterns look plausible and are not supported:

* **`@substrate/engine/*`** (with the wildcard) reaches deep engine subpaths. It exists as an escape hatch for Substrate's own demo, is classified internal, and must not be copied into client code.
* **Relative paths into engine internals**, such as `../../../kernel/color/surface`, couple your code to one engine layout. This is exactly the dependency the [Surface component](/surface-component) was refactored to remove.

The rule in one line: reach all engine behavior through `@substrate/engine`, keep `./` imports to your own colocated files, and use nothing else to leave your directory. If a seam you need is missing from the barrel, the fix is to add it to the barrel rather than to route around it.

***

## The runtime call sequence

Substrate requires a JavaScript runtime on the web — but on the supervised `substrate setup` path you don't write this wiring at all: `setup --apply` generates `src/substrate.setup.ts` (the CSS import plus `initializeSubstrate()`) and wires it into your application entry itself. On the vendored path, the same module is one import and one call:

```ts theme={null}
import '@substrate/generated/global/css/index.gen.css';
import { initializeSubstrate } from '@substrate/engine';

const { brand, preferences } = initializeSubstrate();
```

`initializeSubstrate()` defaults to the first registry brand and `defaultPreferences()`, accepts `{ brand, preferences }` overrides, and is exactly equivalent to the lower-level sequence:

```ts theme={null}
import {
  syncBrandToCssVars, syncPrefsToCssVars, updateAllVars,
  defaultPreferences, BRAND_REGISTRY,
} from '@substrate/engine';

const brand = BRAND_REGISTRY[0];
const prefs = defaultPreferences();

syncBrandToCssVars(brand);   // data-brand + typography, shape, motion, spacing vars
syncPrefsToCssVars(prefs);   // --scheme, --contrast-factor, --density, …
updateAllVars(brand, prefs); // solves APCA, writes per-intent --ucs-* to :root
```

Each call in that sequence has a distinct job:

**`syncBrandToCssVars(brand)`** sets `data-brand="<slug>"` on the root element and writes the brand's static custom properties — typography families and fluid sizing, shape, motion durations, spacing units, effects. Call it once per brand, and again only if the brand changes.

**`syncPrefsToCssVars(prefs)`** writes the raw preference axes to the root: `--scheme`, `--contrast-factor`, `--density`, `--type-scale-factor`, `--motion-factor`, and `--cvd-achromat`. It also toggles the `data-cvd-achromat` attribute, which is what activates the pattern overlays. Everything the generated CSS composes with `calc()` reacts to this call alone.

**`updateAllVars(brand, prefs)`** does the expensive work: it derives the base and elevated surfaces, runs the warmth → cvd → apca pipeline, and writes the solved per-intent `--ucs-*` primitives to `:root`.

On any preference change, repeat the last two:

```ts theme={null}
prefs.scheme = 1;
prefs.contrastFactor = 1.3;

syncPrefsToCssVars(prefs);
updateAllVars(brand, prefs);
```

With the values on `:root`, elements consume them by opting in — that contract is small enough to hold in your head and lives on its own page: [Markup Opt-In](/markup).

### Following OS preferences

The runtime ships helpers that read OS media queries into the vector and keep listening. Each returns a cleanup function that detaches its listeners:

```ts theme={null}
import {
  applyReducedMotion, applyContrastPreference, applyForcedColorsCheck,
  applyCvdFromStorage, persistCvd,
} from '@substrate/engine';

const onChange = () => {
  syncPrefsToCssVars(prefs);
  updateAllVars(brand, prefs);
};

const cleanups = [
  applyReducedMotion(prefs, onChange),      // prefers-reduced-motion → motionFactor 0
  applyContrastPreference(prefs, onChange), // prefers-contrast more → 1.3, less → 0.85
  applyForcedColorsCheck(prefs, onChange),  // forced-colors: active disables CVD
  applyCvdFromStorage(prefs, onChange),     // restore a saved CVD preference
];

// on teardown
cleanups.forEach((stop) => stop());
```

Two things are already automatic before any of these helpers run. The generated CSS bakes a no-JS floor that follows the OS's `prefers-color-scheme` and `prefers-contrast` media queries on its own — a server-rendered page paints accessibly, in the user's OS scheme, before a single byte of JS executes (see [the no-JS floor](/modes/overview#the-no-js-floor)). And `initializeSubstrate()` covers the entire startup sequence. The helpers exist to keep the *live* preference vector following OS signals after startup.

`prefers-color-scheme` is deliberately not among the helpers — scheme is a continuous axis and often an in-app choice, so you decide whether the OS drives it. See [Light & Dark](/modes/light-dark#moving-along-the-axis).

***

<CardGroup cols={2}>
  <Card title="Markup Opt-In" icon="code" href="/markup">
    Required next step: data-ucs and data-mode, the two attributes every consuming element carries.
  </Card>

  <Card title="Surface Component" icon="layer-group" href="/surface-component">
    Required when surfaces nest: re-solving contrast against a local background.
  </Card>

  <Card title="Web" icon="css3" href="/platforms/web">
    The generated CSS layers, the custom property namespaces, and the calc-composed model.
  </Card>

  <Card title="Modes Overview" icon="sliders" href="/modes/overview">
    The preference vector the runtime call sequence is driving.
  </Card>
</CardGroup>
