Skip to content
Transtyle v0.1.0-alpha.5
ok: build 10:17 UTC31 pages main · 7ed21c5

Alpha — breaking changes ship without a deprecation cycle. What is built vs. planned

Your first build

Ten minutes, using the Acme example that ships in the repository. Every output shown on this page is real, produced by running exactly these commands.

1. Set up#

git clone https://github.com/transtyle/transtyle
cd transtyle
npm install          # zero external dependencies — this just links the workspaces
cd examples/acme

2. Look at what Acme decides#

Open tokens/semantic.tokens.json. Acme’s decision layer is deliberately tiny: one brand color, two surfaces, two text colors, a border, a radius, two fonts:

"primary":   { "solid": { "$value": "{option.color.blue.600}" } },
"elevation": { "0": { "surface": { "$value": "{option.color.white}" } },
               "1": { "surface": { "$value": "{option.color.gray.50}" } } },
"text":      { "base":  { "$value": "{option.color.gray.900}" } },
"border":    { "base":  { "$value": "{option.color.gray.200}" } }

The {option.color.blue.600} references point at tokens/option.tokens.json, the raw palette under Acme’s own names. Dark-mode values live alongside. Acme uses the inline form, but separate mode files are the recommended layout for real teams.

3. Build#

npx transtyle build shadcn
authored 14/14 recommended

shadcn  39% native · 53% derived · 8% dropped
  ↳ dist/shadcn/globals.transtyle.css
  ↳ dist/shadcn/usage.md
  ↳ dist/shadcn/report.json
  ↳ dist/shadcn/transtyle-manifest.json

✔ build complete

The first line says Acme authors every slot of the recommended completeness level: brand, neutrals with their dark values, radius and fonts.

The shadcn line is the coverage summary. Under half of shadcn’s variable set came straight from Acme’s decisions. Most of the rest was computed from them, and a sliver was bent to fit. One thing shadcn can’t express was dropped, with a note, not silently.

4. Read the output#

Open dist/shadcn/globals.transtyle.css. Every line says where its value came from:

:root {
  --radius: 0.5rem; /* radius.md */
  --background: oklch(1 0 0); /* color.elevation.0.surface */
  --card: oklch(0.985 0.003 255); /* color.elevation.1.surface */
  --popover: oklch(1 0 0); /* color.elevation.3.surface · derived */
  --primary: oklch(0.55 0.18 255); /* color.primary.solid */
  ...

--background and --primary trace to authored decisions. --popover carries · derived: Acme never decided a popover color, so a rule proposed one from the surface ladder. This file is disposable on purpose: never edit it, regenerate it.

5. Ask why#

The compiler answers for any value:

npx transtyle explain primary.tint
semantic.color.primary.tint = oklch(0.95 0.017 255)  [#e7effa]
 └─ derived by rule mix-toward-surface(0.92)@standard@1
    inputs: semantic.color.primary.solid = oklch(0.55 0.18 255)  [#026fd7]
     └─ aliased → option.color.blue.600
    inputs: semantic.color.elevation.1.surface = oklch(0.985 0.003 255)  [#f9fafc]
     └─ aliased → option.color.gray.50

Read bottom-up: Acme authored a blue and a surface; a named, versioned rule (mix-toward-surface, from the standard@1 pack) mixed them into the subtle tint. Nothing in the output lacks this paper trail.

6. Read the report#

dist/shadcn/report.json grades every variable. Three real entries:

{ "variable": "--accent", "slot": "semantic.color.accent.tint",
  "class": "derived", "provenance": "derived" }

{ "variable": "--input", "slot": "semantic.color.border.field",
  "class": "derived", "provenance": "derived" }

{ "variable": "(mode:density)", "slot": "—", "class": "dropped",
  "note": "density mode dimension not expressed by this target" }

The middle one shows how grading works. shadcn wants a dedicated input-border color, and the catalog has one, border.field, but Acme doesn’t author it. So it defaults to Acme’s own border and is graded derived, not passed off as native. Author border.field and it flips.

The last one: Acme declares a density mode, and shadcn has no such axis, so it’s dropped, with the reason.

To read the whole file as a page, open it in the report viewer: the coverage bar with the same percentages as the terminal, the build’s diagnostics with their file:line, what check.suppress silenced, and every row, filterable by class. It runs in your browser and uploads nothing.

7. Override a proposal#

Any derived value is yours to take over. Author the slot (for example, decide accent.tint yourself in tokens/semantic.tokens.json), rebuild, and the report’s entry flips from derived to authored. Derivation never argues with you.

8. See it on real components#

cd ../..
npm run dev -w acme-demo-shadcn     # the same page in real shadcn/ui components, port 4103

Each example ships one demo project per target, consuming only the compiled dist/. It’s the fastest way to eyeball a theme on the components it will actually style.

Where next#