Targ Apps Docs
Chroma-Style

Runtime hosts

How @chroma/style loads in Portable (Web) and Executable (Chroma Desktop) — same CSS pipeline, different origins and FOUC trade-offs.

Chroma-Style has no native or WASM styling path. Tokens and utilities are ordinary CSS; injectStyles and bootstrapStyle use document APIs available in any Chroma host. Read Runtime modes for the platform vocabulary Portable (Web) and Executable (Chroma Desktop).

Same in every host

BehaviorPortableExecutable (Desktop)
injectStyles()<link rel="stylesheet"> in document.headSame inside the app iframe
Stylesheet URLsnew URL("./tokens.css", import.meta.url) relative to the plugin moduleSame
bootstrapStyle({ cva, cx })Returns tw, presets, utilityClassesIdentical API
data-theme / system darkCSS in tokens.cssIdentical
Production artifactdist/plugins/chroma-style/* copied by chroma buildSame files inside imported .zip

The Desktop shell does not rewrite or bundle your CSS separately. If styles work in a browser build, the same dist/ should look the same when served from Desktop's loopback library server.

Where hosts differ

ConcernPortable (Web)Executable (Desktop)
OriginYour dev server or CDN URL127.0.0.1 dev port or library port 47823 (default)
Dev workflowchroma dev --no-desktop — fastest CSS reload in the browserchroma dev with dev.desktop: true — iframe without automatic CSS hot reload
Stored theme preferencelocalStorage keyed to dev/production URLDifferent origin → separate storage partition
Serving extra CSSChroma-Server serves .css as static filesSame over loopback HTTP (not file://)

Styling does not pick IndexedDB vs filesystem — that split applies to Chroma-Fs, not @chroma/style.

Loading strategies

1. Loader only (templates)

loadPlugins() calls injectStyles() via the manifest styles hook. Minimal setup; CSS may arrive slightly after HTML parse unless the entry module runs immediately.

<head>
  <link rel="stylesheet" href="./plugins/chroma-style/tokens.css" />
  <link rel="stylesheet" href="./plugins/chroma-style/utilities.css" />
  <link rel="stylesheet" href="./src/styles/theme.css" />
</head>

injectStyles() remains idempotent (skips duplicate links).

3. Manual bootstrap without loadPlugins

Static template index.js can call bootstrapStyle after importing the plugin module directly — same API as main.chr.

CSS import limitations

ApproachSupported?
<link rel="stylesheet" href="..."> in index.htmlYes
injectStyles() / duplicate-safe <link> injectionYes
import "./theme.css" from .chr or bundled JSNo — dev server does not treat CSS as ESM
Inline <style> in index.htmlYes (used by standard template demo for FileExplorer chrome)

Checklist before release

  1. Open the built dist/ in a browser (Portable).
  2. Import the same zip into Chroma Desktop (Executable) and spot-check tokens, dark mode, and preset buttons.
  3. If theme is user-configurable, persist it per host or export preference in app data — do not assume localStorage is shared.

On this page