Configuration

All configuration lives in a single beam.config.ts. Beam extracts it at build time with a brace-balanced JSON5 parser - no ts-node or dynamic import required.

Tokens

Tokens are the design system's source of truth. They compile to CSS custom properties and are referenced by name in utilities.

beam.config.ts
import { defineConfig } from 'beamcss'

export default defineConfig({
  tokens: {
    // Named spacing values. Numeric utilities like `gap-4` are always 4px.
    spacing: { card: '1rem', section: '2rem' },

    // Color palette. Referenced by bg-*, text-*, border-*.
    color: {
      base: '#0b0b0c',
      surface: '#16161a',
      fg: '#e8e8ea',
      muted: '#6b7280',
      accent: '#3b82f6',
      'on-accent': '#ffffff',
    },

    radius: { sm: '4px', md: '8px', lg: '16px', full: '9999px' },
    text: { sm: '14px', base: '16px', lg: '20px', xl: '28px' },
    font: { ui: 'Inter, system-ui, sans-serif', mono: 'ui-monospace, monospace' },

    // Breakpoints become variant prefixes (tablet:, desktop:).
    screens: {
      tablet: '48rem',
      desktop: '64rem',
      'mobile-landscape': '(max-width:47.999rem) and (orientation:landscape)',
    },
  },

  // Token names for the body reset's background and color.
  background: 'base',
  foreground: 'fg',
})

Each token category compiles to prefixed CSS custom properties:

CategoryVariable prefixExample
spacing--space-*--space-card: 1rem
color--color-*--color-accent: #3b82f6
radius--radius-*--radius-md: 8px
text--text-*--text-lg: 20px
font--font-*--font-ui: Inter, ...
screens--screen-*--screen-tablet: 48rem

Shortcuts

Named aliases for class strings. Shortcuts expand before compilation, so they accept any valid Beam syntax including variant groups.

beam.config.ts
shortcuts: {
  card: 'flex direction-column gap-4 p-card bg-surface rounded-md',
  center: 'grid place-center',
  'sr-only': 'absolute w-[1px] h-[1px] overflow-hidden',
}
<article class="card hover:(bg-surface+8 scale-105)">
<div class="center h-screen">

The shortcut class name becomes the CSS selector - hover:card applies all ofcard's atoms under :hover.

Recipes

First-class component variants. A recipe has a base applied always and named variants applied selectively. Recipes replace cva, tailwind-variants, and similar runtime helpers.

beam.config.ts
recipes: {
  button: {
    base: 'px-4 py-2 rounded-md hover:scale-105',
    variants: {
      primary: 'bg-accent text-on-accent hover:bg-accent+12',
      secondary: 'bg-surface border border-line hover:bg-surface+8',
      ghost: 'hover:bg-surface',
    },
  },
}
<button class="button">Default</button>
<button class="button:primary">Primary</button>
<button class="hover:button:primary">Hover activates primary</button>

Presets

Plain config fragments merged before local config. Local tokens, shortcuts, recipes, and utility flags always win over preset values. Presets are plain objects - no plugins API, no side effects.

beam.config.ts
export default defineConfig({
  presets: [
    {
      tokens: {
        spacing: { section: '2rem', page: '4rem' },
        color: { brand: '#ff6b35' },
      },
      shortcuts: { center: 'grid place-center' },
    },
  ],
  // Local tokens override preset tokens of the same key:
  tokens: { color: { brand: '#0070f3' } },
})

Utility modules

Tree-shake utility families you don't use. All modules are enabled by default when utilities is omitted.

beam.config.ts
utilities: {
  layout: true,      // flex, grid, position, overflow, sizing, border
  spacing: true,     // p, m, gap
  colors: true,      // bg, text (color), border (color)
  typography: true,  // font, text (size + align), leading, tracking
  effects: true,     // opacity, scale, shadow
}

Disabled utilities produce a compile error rather than silently emitting nothing - so misconfiguration is visible at build time, not in the browser.

Next: Writing styles covers the full class-string grammar.