Skip to content

Repository files navigation

@gitbutler/design-core

Design tokens and fonts for GitButler applications. This package provides CSS custom properties, design tokens in JSON format, and web fonts used across GitButler products.

Installation

npm install @gitbutler/design-core

Usage

Single Import

The easiest way to get everything — fonts, CSS reset, text utilities, and design tokens:

@import "@gitbutler/design-core/core";

Or in JavaScript/TypeScript:

import "@gitbutler/design-core/core";

Design Tokens (CSS)

Import only the design tokens CSS file:

@import "@gitbutler/design-core/tokens";

Or in JavaScript/TypeScript:

import "@gitbutler/design-core/tokens";

This provides CSS custom properties for colors, spacing, typography, and other design tokens with automatic light/dark mode support.

Fonts

Import all font declarations:

@import "@gitbutler/design-core/fonts";

Or reference individual font files directly:

@import "@gitbutler/design-core/fonts/inter/Inter-Variable.woff2";
@import "@gitbutler/design-core/fonts/geist-mono/GeistMono-Variable.woff2";
@import "@gitbutler/design-core/fonts/but-head/But-Head-Regular.woff2";

Styles

Import individual style sheets:

@import "@gitbutler/design-core/styles/reset"; /* CSS reset */
@import "@gitbutler/design-core/styles/text"; /* Text utilities */

CSS Reset

The reset is scoped to @layer reset to avoid specificity conflicts with application styles. It applies the following normalizations:

  • Box sizingbox-sizing: border-box on all elements and pseudo-elements.
  • Font rendering-webkit-font-smoothing: antialiased, -moz-osx-font-smoothing: grayscale, text-rendering: optimizeLegibility, and font size inflation prevention on html.
  • Body defaults — zero padding and margin, overflow-x: hidden, and base values for color, font-family, font-weight, and line-height pulled from design tokens.
  • Form elementsinput, textarea, select, and button have their padding, border, and background stripped, and inherit color and font from the parent.
  • Headingsh1h6 have margin-block removed.
  • Code & precode and pre use var(--fontfamily-mono).
  • Lists & paragraphsul and ol have padding-left and list-style removed; ul, pre, and p have margin-block removed.

Text Utilities

Text classes are scoped to @layer text. The layer also sets three font-family custom properties on :root:

Property Value
--fontfamily-base var(--text-fontfamily-base), sans-serif
--fontfamily-mono var(--text-fontfamily-mono), monospace
--fontfamily-accent var(--text-fontfamily-accent), serif

Size classes set font-size, font-weight: regular, line-height, and font-family: base as a self-contained unit:

Class Font size
.text-10 10px (0.625rem)
.text-11 11px (0.6875rem)
.text-12 12px (0.75rem)
.text-13 13px (0.8125rem)
.text-14 14px (0.875rem)
.text-15 15px (0.938rem)
.text-16 16px (1rem)
.text-accent-head 62px (3.875rem) — display / brand heading

Modifier classes are designed to be composed on top of a size class:

Class Effect
.text-semibold font-weight: var(--text-weight-semibold)
.text-bold font-weight: var(--text-weight-bold)
.text-italic font-style: italic
.text-monospace Switches to var(--fontfamily-mono)
.text-body Switches to the looser var(--text-lineheight-body) line height
.text-balance text-wrap: balance — ideal for short headings
.text-pre white-space: pre-wrap + word-break: break-word — preserves whitespace without overflow

Example usage:

<p class="text-13 text-semibold">Label</p>
<code class="text-12 text-monospace">git commit</code>
<h1 class="text-accent-head text-italic">GitButler</h1>

Available Exports

  • @gitbutler/design-core/core - Single import: fonts + reset + text utilities + tokens
  • @gitbutler/design-core/tokens - CSS custom properties (design tokens)
  • @gitbutler/design-core/fonts - All font CSS declarations
  • @gitbutler/design-core/fonts/* - Individual font files
  • @gitbutler/design-core/styles/reset - CSS reset
  • @gitbutler/design-core/styles/text - Text utility classes

Included Fonts

All fonts are variable fonts unless noted.

  • Inter — Primary UI font (Inter-Variable.woff2, Inter-Variable-Italic.woff2)
  • Geist Mono — Monospace font for code (GeistMono-Variable.woff2)
  • But Head — Brand display font (But-Head-Regular.woff2, But-Head-Italic.woff2)

Development

Design tokens live in Figma and flow into this repo through a fixed pipeline:

Figma variables  ──tokens-bruecke──▶  tokens/json/*.tokens.json  ──terrazzo──▶  tokens/tokens.css

Nothing in tokens/ is edited by hand. tokens/json/*.tokens.json is generated by the export, and tokens/tokens.css is generated from it by the build.

Building

# Install dependencies
npm install

# Build tokens.css from tokens/json
npm run build

# Rebuild on every token change
npm run dev:tokens

npm run build runs scripts/postprocess-light-dark.mjs, which:

  1. runs Terrazzo (tz build) over core.tokens.json and semantic.tokens.json — see terrazzo.config.js — to write tokens/tokens.css;
  2. merges the :root and :root.dark blocks into single light-dark(…) declarations, so light and dark mode need no class switching;
  3. appends box-shadow custom properties generated from fx.tokens.json by scripts/generate-shadow-vars.mjs.

Token files

File Source Consumed by
tokens/json/core.tokens.json core variable collection — raw palette, scales Terrazzo
tokens/json/semantic.tokens.json semantic variable collection — aliases onto core, with light/dark modes Terrazzo
tokens/json/fx.tokens.json Figma effect styles — shadows generate-shadow-vars.mjs

Pulling tokens from Figma

Exports use the tokens-bruecke CLI, the same tool as the Figma plugin, in DTCG 2025.10 format.

Credentials go in a gitignored .env at the repo root:

FIGMA_API_KEY=figd_…      # personal access token, must include the file_variables:read scope
FIGMA_FILE_KEY=…          # the design tokens Figma file
set -a && . ./.env && set +a
npx tokens-bruecke \
  -a "$FIGMA_API_KEY" \
  -f "$FIGMA_FILE_KEY" \
  -c .claude/skills/release-tokens/figma-export.config.json \
  -o tokens/json \
  --split-by-collection

The config file pins the export settings the committed tokens were generated with — hex colors, no scopes, no Figma metadata, effect styles as fx. Changing it rewrites every token file, so leave it alone unless that is the intent.

Two gotchas:

  • The Figma variables REST API requires an Enterprise plan and a token carrying the file_variables:read scope. Without it the export fails with 403. Personal access tokens also expire every 90 days.

  • Every export rewrites a createdAt stamp in each file, so a diff alone does not mean the tokens changed. Check with:

    git diff -U0 tokens/json | grep '^[+-]' | grep -v '^[+-][+-]' | grep -v createdAt

    No output means only timestamps moved — revert and skip the release.

Releasing

Version bumps follow the impact on the generated CSS custom properties, since those are the public API:

Change Bump
Token values tweaked patch
Tokens or collections added minor
Tokens removed or renamed (CSS var names change) major

House style: the version bump lives in the same commit as the token changes, tagged with a bare X.Y.Z annotated tag (no v prefix).

npm version <patch|minor|major> --no-git-tag-version
# commit package.json + tokens/ together
git tag -a "$(node -p "require('./package.json').version")" -m ""

npm publish --dry-run
npm publish                  # prompts for a 2FA one-time code
git push origin main && git push --tags

prepublishOnly rebuilds the CSS, so a published package always matches its committed JSON. Pushing tokens/tokens.css also redeploys the hue-dini site via .github/workflows/deploy-hue-dini.yml.

The whole sequence — export, no-op check, build, bump, commit, tag — is automated as a Claude Code skill in .claude/skills/release-tokens/. Run it with /release-tokens; it stops before npm publish, which stays manual because npm 2FA requires a one-time code.

Color Tool

hue-dini is the tool used to preview and export the GitButler color palette. It applies a single shared luminance scale across all hues — gray, accent, and semantic — so shades at the same step feel visually equivalent regardless of hue.

Live: https://gitbutlerapp.github.io/design-core/

cd tools/hue-dini
pnpm install
pnpm dev

See tools/hue-dini/README.md for more details.

About

The place where we generate design tokens for the app

Resources

Stars

5 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages