Entwickler-Doku
Diese Doku wird noch finalisiert und kann sich weiter ändern, während das Produkt weiterentwickelt wird.
Diese Seite bleibt praktisch: installieren, konfigurieren, eine Datei verbinden, Pfad A oder B bootstrappen, Contexts setzen und CSS exportieren. Wer zuerst das kurze Mental Model braucht, startet mit So funktioniert es. Für den Handoff aus Figma ist die Designer-Doku passend.
1. Voraussetzungen
- Frontend, das ein npm-Paket importieren kann (Next.js, Remix, Vite React/Vue, …)
- TokenIgnite Figma-Plugin streamt für die Datei (Designer:in angemeldet)
- Die TokenIgnite File-ID aus dem Plugin (z. B.
tokenignite-096149) — kein Figma-File-Key - UI nutzt bereits
var(--…), wo Live-Updates sichtbar sein sollen — TokenIgnite injiziert Variablen; Component-Code wird nicht umgeschrieben
npm i -D tokenignite
npx tokenignite init
npx tokenignite --helpinit schreibt nur tokenignite.config.json. Es installiert das Paket nicht.
2. Konfiguration
{
"attributeNames": {
"context": "data-ti-context",
"active": "data-ti-active"
},
"bridgePort": 5678,
"files": [
{
"id": "tokenignite-096149",
"rootSelector": ":root",
"name": "global-foundation",
"exportPath": "./app/styles"
}
]
}| Feld | Zweck |
|---|---|
attributeNames.context | Aktive Design-Contexts (Standard data-ti-context) |
attributeNames.active | Aktiver Stream-Name (Standard data-ti-active) |
bridgePort | Lokaler CLI ↔ Browser-Port nur für Session-Status. Live-Tokens streamen weiterhin direkt in den Browser. |
files[].id | TokenIgnite File-ID (literal) oder "process.env.VAR_NAME" |
files[].rootSelector | Wo Runtime-CSS greift (z. B. :root) |
files[].name | Name für tokenignite run <name> und als data-ti-active-Wert |
files[].exportPath | Export-Verzeichnis → {exportPath}/{name}.css |
In öffentlichen Repos Env-Referenzen für files[].id bevorzugen; in privaten Repos sind Literale in Ordnung.
3. Wie Live-Updates in den Browser kommen
- Figma-Plugin veröffentlicht auf dem Live-Sync-Stream.
- Browser-SDK verbindet nach einmaligem öffentlichem Bootstrap.
- SDK injiziert/aktualisiert ein Runtime-
<style>-Tag mit CSS Custom Properties. - Optional spiegelt das CLI (
tokenignite run <name>) Tokens im Terminal und kann exportieren. Der Bridge-Port dient nicht der Token-Lieferung.
4. Client-Bootstrap — zwei Pfade
Pfad A — Lokal: initTokenIgnite() + CLI Run
Braucht aktives tokenignite run <name>. Die Bridge meldet nur, dass die Session läuft. initTokenIgnite nimmt optional { bridgePort } (Standard 5678) — nicht die volle Config. File-ID und Stream-Name kommen aus der CLI-Session.
// Vite: if (import.meta.env.DEV) {
if (process.env.NODE_ENV === "development") {
import("tokenignite").then(({ initTokenIgnite }) => initTokenIgnite());
// optional: initTokenIgnite({ bridgePort: 5678 })
}tokenignite run global-foundationNach dem CLI-Start: Browser-Tab der App einmal anklicken (oder kurz weg- und zurückwechseln). Path A wartet oft auf diesen Fokus, bevor es verbindet — verhindert Console-Spam ohne aktiven Run.
Pfad B — Closed Staging: runTokenIgnite(target, config)
Closed Staging = produktionsgebaut, zugriffsbeschränkt (nicht öffentliche Production). Kein Terminal-run. Nicht in NODE_ENV === "development" wrappen — das würde TokenIgnite auf einem produktionsähnlichen Staging-Deploy deaktivieren.
Übergib files[].name, eine literale File-ID oder einen Env-Wert, den der Bundler sieht:
import config from "../tokenignite.config.json";
import("tokenignite").then(({ runTokenIgnite }) =>
runTokenIgnite("global-foundation", config)
);
// oder: runTokenIgnite("tokenignite-096149", config);
// oder: runTokenIgnite(process.env.NEXT_PUBLIC_FILE_ID, config);Env-Refs in der Config lösen sich im Browser nur auf, wenn der Bundler sie exponiert (z. B. NEXT_PUBLIC_*). Sonst die aufgelöste ID als target übergeben. Pfad B von öffentlicher Production über Deploy/Zugriffskontrolle fernhalten.
5. Terminal-UI (tokenignite run <name>)
Dashboard an Ort und Stelle. Kompakte Seiten behalten Scrollback; hohe Seiten (besonders CSS) expandieren für natives Scrollen.
[TokenIgnite | Public Beta] Run Mode | Name: global-foundation | File-ID: tokenignite-096149 | Variables: 128
⚠ 12 number variables have Figma scopes that do not resolve to a unique unit → rendered unitless (fallback).
Live Feed (last 100 changed CSS variables):
[CHANGED] spacing:default --spacing-gap-2xl: 32px;
[CHANGED] color:light --color-brand-accent: #f2e932;
Run Mode (2 = View Contexts, 3 = View CSS, 4 = Exit Run Mode & Export CSS, 5 = Exit Run Mode):| Taste | Seite |
|---|---|
1 | Live Feed (Standard) — letzte 100 Änderungen ([ADDED] / [CHANGED] / [RENAMED] / [DELETED]) |
2 | Contexts — copy-paste collectionName:modeName für data-ti-context |
3 | CSS — volle Live-Export-Vorschau |
4 | Beenden und nach {exportPath}/{name}.css exportieren |
5 | Beenden ohne Export |
Variables im Header = eindeutige Figma-Variablen-Entities (ähnlich Collection-Totals in Figma), nicht eine Zeile pro Mode-Wert.
6. Contexts & CSS-Variablen
Figma-Collections/Modes werden zu normalisierten kebab-case-Segmenten (führende 1--Präfixe und Sonderzeichen entfallen). CLI-Seite 2 und Plugin-Filter zeigen dieselben Labels.
<html data-ti-context="color-modes:dark-mode">
<html data-ti-context="color-modes:dark-mode spacing-scale:comfortable">Mehrere Contexts Leerzeichen-getrennt. Matching nutzt CSS ~=.
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="de" data-ti-context="color-modes:dark-mode spacing-scale:comfortable">
<body>{children}</body>
</html>
);
}Optional: System-Farbschema folgen
TokenIgnite erzeugt keine prefers-color-scheme-Queries. Modes steuerst du selbst mit den exakten Labels von CLI-Seite 2:
const mq = window.matchMedia("(prefers-color-scheme: dark)");
function applySystemContext() {
document.documentElement.setAttribute(
"data-ti-context",
mq.matches ? "color-modes:dark-mode" : "color-modes:light-mode"
);
}
applySystemContext();
mq.addEventListener("change", applySystemContext);CSS-Variablennamen
Ohne WEB-Code-Syntax: --{gruppenpfad}-{variablenname} (Collection/Mode nicht im Namen). Explizite WEB-Syntax in Figma gewinnt.
--spacing-gap-2xl: 32px;7. Export-CSS vs. Live-Injection
Live-Validierung injiziert CSS für den aktiven Stream und setzt data-ti-active auf files[].name.
Exportiertes CSS nutzt Smart Cascade: Werte, die in allen Modes einer Collection identisch sind, landen in einer gemeinsamen :is(…[data-ti-context~="…"]…)-Schicht; nur echte Mode-Diffs bleiben in expliziten Blöcken. Der :not([data-ti-active="<name>"])-Guard verhindert, dass Export-Regeln gegen die Live-Injection desselben Streams kämpfen.
:is(
:root:not([data-ti-active="global-foundation"])[data-ti-context~="color-modes:light-mode"],
:root:not([data-ti-active="global-foundation"]) [data-ti-context~="color-modes:light-mode"],
:root:not([data-ti-active="global-foundation"])[data-ti-context~="color-modes:dark-mode"],
:root:not([data-ti-active="global-foundation"]) [data-ti-context~="color-modes:dark-mode"]
) {
--space-md: 1rem;
}
:root:not([data-ti-active="global-foundation"])[data-ti-context~="color-modes:light-mode"],
:root:not([data-ti-active="global-foundation"]) [data-ti-context~="color-modes:light-mode"] {
--surface-container: #f5f5f5;
}
:root:not([data-ti-active="global-foundation"])[data-ti-context~="color-modes:dark-mode"],
:root:not([data-ti-active="global-foundation"]) [data-ti-context~="color-modes:dark-mode"] {
--surface-container: #211f26;
}Exportiertes CSS ist unlayered. Mit Cascade Layers:
@import "./tokens.css" layer(theme);Optional: data-ti-active-Guards in Production-CSS entfernen (Vite)
Guards in der committeden Export-Datei behalten, damit Live-Validierung bei Teammates weiter funktioniert. Das Snippet entfernt sie nur aus Vites Production-Emit — keine Disk-Umschreibung:
import { defineConfig } from "vite";
export default defineConfig(({ mode }) => ({
css: {
postcss: {
plugins:
mode === "production"
? [
{
postcssPlugin: "remove-ti-active",
Rule(rule) {
if (rule.selector.includes("data-ti-active")) {
rule.selector = rule.selector.replace(/:not\(\[data-ti-active=.*?\]\)/g, "");
rule.selector = rule.selector.replace(/\s+/g, " ").trim();
}
},
},
]
: [],
},
},
}));8. End-to-End-Checkliste
- Plugin streamt; TokenIgnite File-ID kopieren
npm i -D tokenignite→npx tokenignite init→files[].id/namesetzen- Pfad A: Bootstrap nur bei
NODE_ENV === "development". Pfad B: ohne diesen Guard; von öffentlicher Production fernhalten - Pfad A:
tokenignite run <name>→ App-Tab einmal klicken → Header zeigt Name, File-ID, Variables-Anzahl - Figma-Variable ändern → Style-Tag im Browser aktualisiert sich; Live Feed zeigt
[CHANGED]/[ADDED] data-ti-contextvon der Contexts-Seite setzen → Mode-Overrides greifen- Mit
4exportieren, wenn bereit
9. SDK aktuell halten
npm install tokenignite@latestLiegt die Installation unter der Server-Mindestversion, wird Connect blockiert und die Console zeigt den Upgrade-Hinweis.
10. Troubleshooting
| Symptom | Lösung |
|---|---|
| Upgrade required / keine Verbindung | npm install tokenignite@latest |
| Keine Live-Updates | Plugin streamt? Korrektes files[].id und name? Bei Pfad A läuft tokenignite run? |
initTokenIgnite wartet ewig | tokenignite run <name> starten; bridgePort angleichen |
| Run läuft, aber keine Styles im Browser | App-Tab einmal klicken (Path-A-Fokus-Reconnect); CLI-Run aktiv lassen |
| Env-ID leer im Browser | Mit NEXT_PUBLIC_* (o. ä.) exponieren oder aufgelöste ID an runTokenIgnite übergeben |
| UI ändert sich nicht | Injiziertes <style>-Tag prüfen; Komponenten brauchen passende var(--…) / Figma-Code-Syntax |
| TokenIgnite in öffentlicher Production | Pfad A: hinter NODE_ENV === "development". Pfad B: nur Closed Staging. Bevorzugt devDependency. |
| Port belegt | bridgePort ändern oder Port freigeben |
11. Accounts
- Live-Stream lokal oder auf Closed Staging konsumieren braucht kein Entwickler-TokenIgnite-Konto.
- Du brauchst weiterhin die File-ID der Designer:in und einen aktiven Plugin-Stream.
- Workspace-Mitgliedschaft (Teilen in der Produkt-UI) ist getrennt und kann Anmeldung erfordern — auch wenn die File-ID bekannt ist.