# Crosswake Token Distribution
This guide documents the single distribution mechanism for Crosswake's design tokens:
where they come from, how to regenerate them, what ships in the Hex package, and how
consumers receive them.
## Source
`crosswake.tokens.json` — W3C DTCG 2025.10 format, frozen v9.0 brand contract.
This file is the authoritative origin of every `--cw-*` CSS custom property. All
edits to the brand token values happen here and nowhere else.
## Generate
Run one Node command from the repository root:
```
node brandbook/tools/compile-tokens.js
```
This produces two outputs:
- `brandbook/tokens/tokens.css` — brand book reference copy, linked by `brandbook/index.html`
- `priv/static/crosswake/tokens.css` — distributable copy that ships in the Hex package
Both files are byte-identical. Diff them to verify parity:
```
diff brandbook/tokens/tokens.css priv/static/crosswake/tokens.css
```
No output means the copies are in sync. A non-zero exit or any diff output means one
of the files was edited by hand or a regeneration was only partially applied.
No toolchain beyond Node is required. There is no build system, bundler, or separate
CSS preprocessor involved in generating the token file.
## What ships in the package
`priv/static/crosswake/tokens.css` is in the `priv/` directory tree, which is
explicitly included in the Hex `files:` whitelist in `mix.exs`:
```elixir
files: ~w(lib priv mix.exs README.md LICENSE CHANGELOG.md guides)
```
The `brandbook/` tree is excluded from the package. The brand book reference copy
(`brandbook/tokens/tokens.css`) is a development and documentation artifact only
and is never published to Hex.
## How consumers receive tokens.css
### Via `mix crosswake.gen.offline_ui`
Running the generator task copies `priv/static/crosswake/tokens.css` into the host's
`priv/static/assets/tokens.css` (no-clobber: if that file already exists the generator
logs "reused" and skips the write, preserving any host customizations).
The generated `offline_root.html.heex` template links `tokens.css` before `app.css`:
```html
<link rel="stylesheet" href="/assets/tokens.css" />
<link rel="stylesheet" href="/assets/app.css" />
```
This ensures all `--cw-*` custom properties are defined before any rule that
consumes them.
### Direct Phoenix host
Copy `priv/static/crosswake/tokens.css` from the installed Crosswake dependency into
your host's static CSS directory:
```
cp deps/crosswake/priv/static/crosswake/tokens.css priv/static/css/tokens.css
```
Then link it in your layout before `app.css`:
```html
<link rel="stylesheet" href="/css/tokens.css" />
<link rel="stylesheet" href="/css/app.css" />
```
`tokens.css` must load before `app.css` so that `--cw-*` custom properties are
defined before any rules that reference them via `var(--cw-*)`.
## Contract
- **Never hand-edit `tokens.css` in any consumer.** Edit `crosswake.tokens.json` and
regenerate with `node brandbook/tools/compile-tokens.js`. Hand-edited copies will
drift from the source of truth and break on the next regeneration.
- **Both generated copies must remain byte-identical.** `brandbook/tokens/tokens.css`
and `priv/static/crosswake/tokens.css` are both outputs of the same compile step.
Diff them to confirm parity before committing a regeneration.
- **All `--cw-*` custom properties are defined in `tokens.css`.** Consuming rules
reference them via `var(--cw-*)` and must not duplicate or redefine these values
in host stylesheets.
- Phase 109 adds a CI gate that asserts byte-identical parity with `diff` on every
pull request. Until that gate lands, parity is enforced by convention and the
diff command above.