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.
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:
| Category | Variable prefix | Example |
|---|---|---|
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.
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.
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.
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.
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.