Underlith logo Underlith

Tokens

Design decisions expressed as contracts.
Not components. Not styles. The layer everything else consumes.

Three types, one pipeline

Underlith organizes tokens into three distinct types. Each type has a single responsibility —
and together they form the pipeline from raw values to your publishable brand package.

Base tokens Raw scales. Numbers, sizes, durations. Framework primitives. --ul-space-4, --ul-radius-md
Brand tokens Your org's values. Colors, typography, identity decisions. --ul-color-brand-primary
Semantic aliases Intent over value. What something means, not what it is. --ul-color-text, --ul-color-bg-surface

When you run underlith brand init, Underlith separates brand tokens from base tokens and scaffolds them into a publishable @your-org/tokens package. Semantic aliases travel with the brand layer.


Base tokens

Framework primitives. Raw values that define the scale of your system. These live in the Underlith package and are shared across all consumers.

Spacing spacing.css

The spacing scale used across the system. Replaces arbitrary values like 8px or 12px with a consistent, named scale.

--ul-space-1
--ul-space-2
--ul-space-3
--ul-space-4
--ul-space-5

Typography typography.css

Typographic scales as tokens. Describes intent — not headings or text styles.

--ul-font-size-sm
--ul-font-size-md
--ul-font-size-lg
--ul-line-height-tight
--ul-font-weight-regular

Radius & Borders radius-and-borders.css

Shape-related decisions. Ensures consistent geometry across all consumers.

--ul-radius-sm
--ul-radius-md
--ul-radius-lg
--ul-border-width-hairline

Elevation elevation.css

Depth tokens. Relative depth, not specific components.

--ul-elevation-1
--ul-elevation-2
--ul-elevation-3

Opacity opacity.css

Named transparency levels. Avoids arbitrary alpha values.

--ul-opacity-disabled
--ul-opacity-muted
--ul-opacity-overlay

Breakpoints breakpoints.css

Responsive thresholds as tokens. Defines when layout decisions change.

--ul-breakpoint-sm
--ul-breakpoint-md
--ul-breakpoint-lg

Motion motion.css

Durations, easings, delays, and composite motion tokens. Use individual tokens for fine control, or composite tokens for common effects.

Durations

--ul-duration-nano
--ul-duration-micro
--ul-duration-fast
--ul-duration-base
--ul-duration-moderate
--ul-duration-slow
--ul-duration-glacial
--ul-duration-epic

Easing

--ul-ease-linear
--ul-ease-enter
--ul-ease-enter-back
--ul-ease-enter-spring
--ul-ease-exit
--ul-ease-exit-sharp
--ul-ease-inout
--ul-ease-inout-soft
--ul-ease-inout-strong
--ul-ease-bounce
--ul-ease-bounce-strong
--ul-ease-elastic
--ul-ease-anticipate

Composite motion tokens

--ul-motion-drop-bounce
--ul-motion-fade-up
--ul-motion-fade-in
--ul-motion-scale-pop
--ul-motion-glow-breath
--ul-motion-pulse
--ul-motion-float
--ul-motion-shimmer
--ul-motion-skeleton

Brand tokens

Your org's identity decisions. Colors, brand palette, identity values. These are the tokens that underlith brand init extracts and packages into your publishable @your-org/tokens.

Colors colors.css

Raw color values. Value-based, without semantic context. Your brand palette lives here.

--ul-color-brand-300
--ul-color-brand-500
--ul-color-neutral-0
--ul-color-neutral-900

Semantic aliases

The most important layer. Maps raw tokens to intent — what something means, not what it looks like. Semantic aliases are what components consume. When your brand evolves, you update the alias. Components never change.

Semantic aliases semantic-aliases.css

/* Text */
--ul-color-text
--ul-color-text-secondary
--ul-color-text-inverse

/* Surfaces */
--ul-color-bg-surface
--ul-color-bg-elevated

/* Borders */
--ul-color-border-subtle
--ul-color-border-strong

/* Interactive */
--ul-color-brand-primary
--ul-color-brand-primary-hover

Semantic aliases travel with your brand package. When you publish @your-org/tokens, any project that installs it gets the complete alias map — and can safely use var(--ul-color-text) without ever knowing what the underlying value is.