substrate init, wiring the three public import aliases, and initializing the runtime so your app computes APCA-solved token values. By the end, your app renders through the Substrate cascade and you’ve verified it. APCA attribution and use restrictions: see About APCA.
1. Obtain Substrate
The CLI comes from npm:npx @unknown-creatives/substrate <cmd>. The engine is delivered separately and is never published to npm — clone the Substrate checkout you received from Unknown Creatives outside your project, then vendor the engine into your repo:
node_modules or any install step inside your repo. Vendor the whole src/ directory — if src/kernel/, src/platforms/, or src/types/ is missing, init reports each as a blocker and exits non-zero.
Before running init, confirm the layout is detectable (--dry-run writes nothing):
Found Substrate (client): substrate/engine.
2. Run substrate init
From your project root:
substrate <cmd> spelling in the rest of this guide means that scoped npx invocation.
Working on Substrate itself? Run the bin from your checkout instead — after
(cd "$SUBSTRATE_REPO" && npm ci), a shell function makes the bare spelling literal: substrate() { node "$SUBSTRATE_REPO/packages/cli/bin/substrate-init.js" "$@"; }init prints the Substrate it found, lets you pick which AI tools to configure, links the Substrate skills and the Bloom agent into each selected tool, scaffolds the client overlays, writes .substrate/state.yaml, and sets up the import aliases. Non-interactive alternatives:
The
--platform flag selects an AI coding tool (claude-code, cursor, windsurf, …) — it is not an output-target selector. Re-running init is idempotent, and substrate init --refresh replays your recorded selections. The full CLI surface is init, add, upgrade, adopt, setup, and artifact.3. Wire the three public aliases
Client code imports Substrate through exactly three public aliases — this is the whole import contract, and an engine swap never changes these import statements:init auto-writes the aliases into tsconfig.json (idempotent; it manages only the @substrate/* zone and never touches your other options):
init doesn’t edit them — it writes an importable manifest, .substrate/aliases.js, that you spread into your bundler’s alias config:
substrate init --report-aliases.
4. First import
Two things run at app startup: load the generated CSS barrel once at your app entry (it establishes the full cascade), then initialize the engine — the runtime APCA solver, the only JS Substrate requires. On the vendored path you add this yourself; on the supervisedsubstrate setup path this exact module is generated for you as src/substrate.setup.ts:
Any element then opts into the cascade with data-ucs plus a data-mode role (the full attribute contract is on Markup Opt-In):
To move along the scheme axis (light ↔ dark), update the preference vector and re-sync — the CSS reacts automatically:
scheme is a continuous value (0 → 1), the runtime sets data-brand on the root itself, and named modes like dark or highContrast are presets over the same continuum — see Core Concepts.
5. Verify
These checks need nothing beyond Node and whatinit wrote:
6. Discover catalog content
Substrate ships a catalog of starting-point content — component configs, brand configs — that you scaffold into your client-owned content root as you need it:add scaffolds the entry’s files with provenance headers, records the fetch in .substrate/manifest.yaml, and runs your generate command so the pipeline picks the new config up immediately.
Runtime & Imports
The required wiring in depth: the alias contract, the three-call sequence, and the OS preference helpers.
Surface Component
Required when surfaces nest — cards, panels, insets — so contrast is re-solved against the local background.
Core Concepts
The runtime-solver mental model: intents, the preference vector, APCA solving per surface, and the cascade.
Brand Config Overview
Author your own brand: the YAML schema, the open intents map, and the flexibility bounds.