No description
  • JavaScript 40.6%
  • TypeScript 25.9%
  • CSS 23.6%
  • SCSS 9.9%
Find a file
Flo 2368e00f32
All checks were successful
package-tokens / Publish to Forgejo NPM registry (push) Successful in 16s
bump version
2026-08-15 14:57:16 +02:00
.forgejo/workflows fix ci 2026-08-15 14:28:36 +02:00
build Initial commit 2026-08-15 14:27:43 +02:00
handoff Initial commit 2026-08-15 14:27:43 +02:00
source Initial commit 2026-08-15 14:27:43 +02:00
.gitignore Initial commit 2026-08-15 14:27:43 +02:00
package.json bump version 2026-08-15 14:57:16 +02:00
pnpm-lock.yaml fix nuxt-ui.ts export 2026-08-15 14:56:40 +02:00
pnpm-workspace.yaml Initial commit 2026-08-15 14:27:43 +02:00
README.md Initial commit 2026-08-15 14:27:43 +02:00
tsconfig.build.json fix nuxt-ui.ts export 2026-08-15 14:56:40 +02:00

node-K · Design Tokens (@node-k/tokens)

Geteilt werden nur Werte — Farben, Typografie, Raster, Kanten, Effekte und Formen. Komponenten bleiben in jeder App eigenständig: die Nuxt-UI-App (Tailwind) und die Angular-App (Bootstrap) besitzen ihr eigenes Markup und ihre eigenen Styles und ziehen ausschließlich Werte aus diesem Paket.

tokens/
  source/                 ← EINZIGE Quelle der Wahrheit (DTCG-JSON)
    color/brand.json        Neutrale, Marke, DNA-Aliase
    color/semantic.json     Text-Rampe, Semantik, Rollen-Aliase
    font/family.json        Familien-Stacks
    font/scale.json         Größe · Gewicht · Breite · Zeilenhöhe · Laufweite
    size/space.json         8px-Skala, Layout, Icon-Ausgabegrößen
    size/radius.json        Radien, Rahmenstärken
    shape/geometry.json     u-Raster, Fasen-Ratios, Strichstaffel, Icon-Raster
    shape/clip.json         benannte Formen (clip-path) — strukturiert, nicht als CSS
    effect/shadow.json      Schatten, Glow
    effect/motion.json      Easing, Dauer, Fokus, Punktraster-Gradienten
    asset/font.json         Tektur- + JetBrains-Mono-Dateien (selbst gehostet)

  build/                   ← Style-Dictionary-Toolchain
    shape.mjs                Fasen-Renderer: {cut,corners,size} → polygon(…)
    tailwind-css.mjs         Namensgebung + @theme-Ausgabe für Tailwind v4
    transforms.mjs           Namens- und Form-Transforms + Transform-Groups
    formats.mjs              SCSS-Maps, Tailwind-@theme, @font-face, flaches JSON
    style-dictionary.config.mjs
    copy-static.mjs          kopiert build/static/* nach dist/ nach jedem Build
    static/
      _nodek-bootstrap.scss  KURIERT · Bootstrap-Variablen-Brücke, nie generiert

  dist/                    ← GENERIERT, nicht eingecheckt (.gitignore) — entsteht
                              durch `npm run build`, bzw. automatisch beim
                              `npm install` dieses Pakets (prepare-Hook)
    css/nodek-tokens.css      :root{--nk-…}  · alle Werte, Referenzen bleiben live
    css/nodek-fonts.css       @font-face · Tektur + JetBrains Mono, self-hosted
    scss/_nodek-tokens.scss   $nk-…: value !default
    scss/_nodek-maps.scss     $nk-color, $nk-space, $nk-shape … als SCSS-Maps
    scss/_nodek-bootstrap.scss  KURIERT (kopiert aus build/static/)
    tailwind/theme.css        @theme-Block + --shape-*-Properties + @utility
    nodek-tokens.json         flach aufgelöst, für Tests und Doku

  handoff/                 ← Integrations-Kit für die Nuxt-UI-App
    design-tokens.md          Referenztabelle + Gestaltungsregeln
    newsletter-component.md   Beispiel-Komponente mit den Tokens
    nuxt-ui.md / nuxt-ui.css / nuxt-ui.ts   Mapping-Layer auf Nuxt UI 4
    tailwind-v4.md            CSS-first Tailwind-v4-Einbindung

  package.json              npm-Paket "@node-k/tokens"

Bauen: npm install && npm run build. Der prepare-Hook baut automatisch bei jedem npm install — auch wenn eine App dieses Paket als Git- oder Pfad-Abhängigkeit installiert, entsteht dist/ dort mit.


Token-Schema

DTCG-Notation ($value / $type / $description), Style Dictionary 4.

{
  "color": {
    "brand": {
      "orange": { "$type": "color", "$value": "#fbaa2b" }
    },
    "role": {
      "accent": { "$type": "color", "$value": "{color.brand.orange}",
        "$extensions": { "nodek": { "cssVar": "nk-accent" } } }
    }
  }
}

Pfad = Bedeutung. <kategorie>.<gruppe>.<name>; erste Ebene ist die Kategorie (color, font, space, radius, border, shape, shadow, motion, focus, gradient, size, layout, asset).

Referenzen ({pfad}) statt Wiederholung. Basiswerte liegen in color.neutral / color.brand; alles Bedeutungstragende (color.role.accent, color.dna.gelb) ist ein Alias. Im CSS-Output bleiben Referenzen als var() erhalten — ein Theme-Wechsel wirkt zur Laufzeit.

$extensions.nodek.cssVar friert den gewachsenen CSS-Namen ein (--nk-orange statt --nk-color-brand-orange). Damit ist der CSS-Output 1:1 kompatibel mit dem bestehenden Designsystem; SCSS und Tailwind benutzen die saubere Pfad-Notation.

Eigene $type-Werte (Präfix nk.) für alles, was DTCG nicht abbildet: nk.clipPath, nk.transform, nk.transition, nk.border, nk.gradient, nk.percentage, nk.fontFace. Schatten liegen als CSS-String statt als zerlegtes DTCG-Objekt — bewusste Abweichung, weil beide Apps sie unverändert durchreichen.


Formen als Tokens

Das prägende Merkmal der Marke ist die 45°-Fase. Sie darf nicht als polygon(…)-String in zwei Codebasen liegen. Deshalb ist eine Form ein strukturiertes Token:

"shape": {
  "clip": {
    "btn": {
      "$type": "nk.clipPath",
      "$value": { "cut": "chamfer", "corners": ["tr", "bl"], "size": "{shape.chamfer.btn}" }
    }
  }
}

build/shape.mjs rendert daraus im Uhrzeigersinn ab oben links — für jede Plattform dieselbe Geometrie, mit der Fasengröße als eigener Variable:

/* dist/css/nodek-tokens.css — Designsystem, Bestandsnamen */
--nk-clip-btn: polygon(0 0, calc(100% - var(--nk-cham-btn)) 0, );

/* dist/tailwind/theme.css — Tailwind v4 */
--shape-btn-clip: polygon(0 0, calc(100% - var(--shape-btn-chamfer)) 0, );

Vorteile: die Fasengröße ist ein eigener, referenzierbarer Wert (shape.chamfer.btn = 8px); die Eckenwahl ist deklarativ und prüfbar; alle drei Ausgabeformate erhalten dieselbe Geometrie; eine neue Form ist ein Eintrag, kein Copy-Paste.

Token Ecken Fase Einsatz
shape.clip.btn tr · bl 8px Schaltflächen — die Signatur
shape.clip.btn-inner tr · bl 7px Innenfläche verschachtelter Buttons
shape.clip.chip tr · bl 6px Chips, Tags, Badges
shape.clip.card tr 12px Karten, Container
shape.clip.card-inner tr 11px Innenfläche verschachtelter Karten
shape.clip.panel tr · bl 16px Großflächen, Signalflächen
shape.clip.tile tr 16px Bild-/Medienkachel
shape.clip.octagon alle vier 12px Avatar, Marken-Kachel, Foto-Oktagon

Regel: Fase = 0.3 · kürzere Kante, gerundet, geklammert auf diese Klassen. Richtung immer oben rechts + unten links; nur Behälter-Flächen tragen ausschließlich oben rechts. Ältere Karten im Designsystem nutzen teils oben links + unten rechts — das ist Altbestand und wandert bei Gelegenheit auf die Tokens.


Konsumieren

Das Paket veröffentlicht seine generierten Dateien über exports-Subpfade (siehe package.json) — kein tiefer Import in dist/** nötig.

Nuxt UI / Tailwind v4 — CSS-first, kein JS-Plugin

/* app.css / main.css */
@import "tailwindcss";
@import "@node-k/tokens/fonts";
@import "@node-k/tokens/tailwind";

Details und die vollständige Mapping-Anleitung für Nuxt UI 4 stehen in handoff/tailwind-v4.md und handoff/nuxt-ui.md.

theme.css (Export ./tailwind) besteht aus drei Teilen:

  1. @theme { … } — alles, was einem Tailwind-v4-Namespace entspricht, und damit Utilities erzeugt: --color-nk-*bg-nk-orange, --font-nk-*font-nk-display, --text-nk-*text-nk-h1, --spacing-nk-*, --radius-nk-*, --shadow-nk-*, --font-weight-nk-*, --leading-nk-*, --tracking-nk-*, --ease-nk, --container-nk.
  2. :root { … } — alles ohne Namespace, direkt per var() nutzbar: --shape-btn-clip, --shape-btn-chamfer, --shape-stroke-reg, --shape-icon-box, --nk-border-hair, --nk-duration-fast, --nk-transition, --nk-focus-offset, --nk-dots-orange.
  3. @utility … — Tailwinds nativer Utility-Mechanismus für die Formen: nk-clip-btn, nk-clip-chip, nk-clip-card, nk-clip-panel, nk-clip-tile, nk-clip-octagon, plus nk-focus.
<button class="nk-clip-btn bg-nk-orange font-nk-display text-nk-body px-6 py-3">
  Mitglied werden
</button>

@theme erweitert die Tailwind-Defaults. Wer ausschließlich node-K-Werte zulassen will, setzt vor dem Import @theme { --*: initial; }.

Nuxt UI erwartet für ui.primary eine 50950-Palette. node-K hat bewusst keine Tint-Rampe (Schwarz ist die Bühne, Akzente sind gesetzt). Entweder ui: { primary: 'amber' } mit --color-amber-500: var(--color-nk-orange), oder die Nuxt-UI-Farbrollen direkt auf --color-nk-* zeigen lassen. Keine neuen Tints erfinden.

Bootstrap / Angular

@use 'pkg:@node-k/tokens/scss' as *;
@use 'pkg:@node-k/tokens/scss-bootstrap' as *;
@import 'bootstrap/scss/bootstrap';
.btn-primary { clip-path: $nk-shape-clip-btn; border-radius: 0; }

(pkg:-URLs setzen Dart Sass ≥ 1.71 voraus; alternativ node_modules als Sass-Loadpath eintragen und @use 'nodek-tokens' as *; / @use 'nodek-bootstrap' as *; schreiben.)

Beliebige Umgebung (Web Components, E-Mail, Doku)

<link rel="stylesheet" href="/node_modules/@node-k/tokens/dist/css/nodek-fonts.css">
<link rel="stylesheet" href="/node_modules/@node-k/tokens/dist/css/nodek-tokens.css">

Grenze: was geteilt wird, was nicht

Geteilt — Farben, Typografie, 8px-Raster, Radien, Rahmenstärken, Fasen und Formen, Schatten, Glow, Easing/Dauer, Fokus-Werte, Icon-Raster und Ausgabegrößen, Font-Dateien.

Nicht geteilt — Komponenten-Markup, Klassennamen, Zustandslogik, Layout- Entscheidungen, Bootstrap-Utilities, Nuxt-UI-Slots, Breakpoints (beide Frameworks haben eigene und inkompatible Definitionen), Icon-SVGs (die liegen weiterhin in assets/svg/ und werden als Dateien kopiert, nicht als Token).

Verboten: einen Wert in einer App hart schreiben, der schon Token ist — und ein Token anlegen, das nur eine App braucht.


Änderungen

  1. Wert in source/** ändern oder anlegen (mit $description).
  2. npm run build in tokens/.
  3. Nichts committen — dist/ ist generiert und gitignored. Konsumierende Apps installieren @node-k/tokens (Git- oder Pfad-Abhängigkeit); der prepare-Hook baut dist/ dort automatisch aus derselben Quelle.
  4. Bei neuem CSS-Namen: $extensions.nodek.cssVar nur setzen, wenn ein bestehender Name erhalten bleiben muss.

Root-styles.css importiert dist/css/nodek-fonts.css und dist/css/nodek-tokens.css direkt — das ist die einzige Werte-Quelle für das Designsystem selbst, es gibt keine parallele handgeschriebene CSS-Ebene mehr.