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
Terminal
npm i -D tokenignite
npx tokenignite init
npx tokenignite --help

init schreibt nur tokenignite.config.json. Es installiert das Paket nicht.

2. Konfiguration

JSON
{
  "attributeNames": {
    "context": "data-ti-context",
    "active": "data-ti-active"
  },
  "bridgePort": 5678,
  "files": [
    {
      "id": "tokenignite-096149",
      "rootSelector": ":root",
      "name": "global-foundation",
      "exportPath": "./app/styles"
    }
  ]
}
FeldZweck
attributeNames.contextAktive Design-Contexts (Standard data-ti-context)
attributeNames.activeAktiver Stream-Name (Standard data-ti-active)
bridgePortLokaler CLI ↔ Browser-Port nur für Session-Status. Live-Tokens streamen weiterhin direkt in den Browser.
files[].idTokenIgnite File-ID (literal) oder "process.env.VAR_NAME"
files[].rootSelectorWo Runtime-CSS greift (z. B. :root)
files[].nameName für tokenignite run <name> und als data-ti-active-Wert
files[].exportPathExport-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

  1. Figma-Plugin veröffentlicht auf dem Live-Sync-Stream.
  2. Browser-SDK verbindet nach einmaligem öffentlichem Bootstrap.
  3. SDK injiziert/aktualisiert ein Runtime-<style>-Tag mit CSS Custom Properties.
  4. 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.

TypeScript
// Vite: if (import.meta.env.DEV) {
if (process.env.NODE_ENV === "development") {
  import("tokenignite").then(({ initTokenIgnite }) => initTokenIgnite());
  // optional: initTokenIgnite({ bridgePort: 5678 })
}
Terminal
tokenignite run global-foundation

Nach 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:

TypeScript
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.

Terminal
[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):
TasteSeite
1Live Feed (Standard) — letzte 100 Änderungen ([ADDED] / [CHANGED] / [RENAMED] / [DELETED])
2Contexts — copy-paste collectionName:modeName für data-ti-context
3CSS — volle Live-Export-Vorschau
4Beenden und nach {exportPath}/{name}.css exportieren
5Beenden 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
<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 ~=.

TypeScript
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:

JavaScript
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.

CSS
--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.

CSS
: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:

CSS
@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:

JavaScript
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

  1. Plugin streamt; TokenIgnite File-ID kopieren
  2. npm i -D tokenignitenpx tokenignite initfiles[].id / name setzen
  3. Pfad A: Bootstrap nur bei NODE_ENV === "development". Pfad B: ohne diesen Guard; von öffentlicher Production fernhalten
  4. Pfad A: tokenignite run <name> → App-Tab einmal klicken → Header zeigt Name, File-ID, Variables-Anzahl
  5. Figma-Variable ändern → Style-Tag im Browser aktualisiert sich; Live Feed zeigt [CHANGED] / [ADDED]
  6. data-ti-context von der Contexts-Seite setzen → Mode-Overrides greifen
  7. Mit 4 exportieren, wenn bereit

9. SDK aktuell halten

Terminal
npm install tokenignite@latest

Liegt die Installation unter der Server-Mindestversion, wird Connect blockiert und die Console zeigt den Upgrade-Hinweis.

10. Troubleshooting

SymptomLösung
Upgrade required / keine Verbindungnpm install tokenignite@latest
Keine Live-UpdatesPlugin streamt? Korrektes files[].id und name? Bei Pfad A läuft tokenignite run?
initTokenIgnite wartet ewigtokenignite run <name> starten; bridgePort angleichen
Run läuft, aber keine Styles im BrowserApp-Tab einmal klicken (Path-A-Fokus-Reconnect); CLI-Run aktiv lassen
Env-ID leer im BrowserMit NEXT_PUBLIC_* (o. ä.) exponieren oder aufgelöste ID an runTokenIgnite übergeben
UI ändert sich nichtInjiziertes <style>-Tag prüfen; Komponenten brauchen passende var(--…) / Figma-Code-Syntax
TokenIgnite in öffentlicher ProductionPfad A: hinter NODE_ENV === "development". Pfad B: nur Closed Staging. Bevorzugt devDependency.
Port belegtbridgePort ä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.