Getting started

Calibrate is a code-first design system distributed as npm packages for websites, web applications, and design-in-browser workflows.


Calibrate turns Measured’s brand system into code: components, CSS, tokens, assets, and tooling for web projects. Calibrate’s public packages are split by responsibility.

  • @measured/calibrate-assets: fonts and favicons
  • @measured/calibrate-config: linting and editor tooling
  • @measured/calibrate-core: primary components and CSS
  • @measured/calibrate-markdown: Markdown rendering utility
  • @measured/calibrate-react: React components for web applications
  • @measured/calibrate-skills: agent and team guardrails
  • @measured/calibrate-tokens: structured data for agents and tooling

Choose an integration route

Choose the route that matches how your project renders UI. Both routes use the same components, CSS, tokens, fonts, and tooling rules.

  1. HTML / SSR. Use @measured/calibrate-core directly if rendering HTML on the server, building an Eleventy or Astro-style site, or want framework-neutral output.
  2. React. Use @measured/calibrate-react when building a React app.

Install for HTML / SSR

Install the core runtime, CSS, and recommended tooling packages:

pnpm add @measured/calibrate-core @measured/calibrate-assets
pnpm add -D eslint stylelint @measured/calibrate-config @measured/calibrate-skills @measured/calibrate-tokens

Install for React

Install the React adapter alongside the shared core and assets packages:

pnpm add react react-dom @measured/calibrate-react @measured/calibrate-core @measured/calibrate-assets
pnpm add -D eslint stylelint @measured/calibrate-config @measured/calibrate-skills @measured/calibrate-tokens

Load fonts and CSS

Load fonts before Calibrate core styles. This is the current setup for both HTML and React consumers:

@import "@measured/calibrate-assets/fonts.css";
@import "@measured/calibrate-core/styles.css";

If your stack prefers JS entrypoints, keep the same order:

import "@measured/calibrate-assets/fonts.css";
import "@measured/calibrate-core/styles.css";

For app icons, copy the favicon assets from @measured/calibrate-assets into your static public directory and reference them from root-relative URLs.

Set the Calibrate root

Wrap every Calibrate UI in a Root component. Use renderClbrRoot for HTML / SSR output, <Root> in React.

HTML / SSR example

Render HTML with @measured/calibrate-core component renderers:

import {
  defineClbrComponents,
  renderClbrBox,
  renderClbrButton,
  renderClbrHeading,
  renderClbrRoot,
  renderClbrStack,
  renderClbrText,
} from "@measured/calibrate-core";

const page = renderClbrRoot({
  appRoot: true,
  children: renderClbrBox({
    paddingBlock: "lg",
    paddingInline: "lg",
    responsive: true,
    children: renderClbrStack({
      gap: "sm",
      children: [
        renderClbrHeading({ level: 1, text: "Hello" }),
        renderClbrText({ as: "p", children: "Calibrate is wired up." }),
        renderClbrButton({ label: "Continue" }),
      ].join(""),
    }),
  }),
});

// Register Calibrate components once in the browser.
defineClbrComponents();

React example

import {
  defineClbrAll,
  Button,
  Heading,
  Root,
  Stack,
  Text,
} from "@measured/calibrate-react";

// Register Calibrate components once at app startup.
defineClbrAll();

export function App() {
  return (
    <Root appRoot>
      <Stack gap="sm" responsive>
        <Heading level={1}>Hello</Heading>
        <Text as="p">Calibrate is wired up.</Text>
        <Button label="Continue" />
      </Stack>
    </Root>
  );
}

Root output

Both routes emit the markup that Calibrate styles target:

<div class="clbr" data-clbr-brand="msrd">...</div>

Theme and surface

Theme and surface are part of the component model. By default, Calibrate follows the user’s light or dark mode preference. Force a theme with the Root theme prop when needed, and use Surface or component-level surface props for local color context.

  • Root theme accepts light or dark.
  • Surface variant accepts default or brand.
  • Surface contentTheme accepts light or dark when foreground content needs to be locked to a specific theme.
import { renderClbrRoot, renderClbrSurface } from "@measured/calibrate-core";

const html = renderClbrRoot({
  theme: "dark",
  children: renderClbrSurface({
    variant: "brand",
    contentTheme: "light",
    children: "...",
  }),
});
import { Root, Surface } from "@measured/calibrate-react";

export function Example() {
  return (
    <Root theme="dark">
      <Surface variant="brand" contentTheme="light">
        ...
      </Surface>
    </Root>
  );
}

Compose first

Build with Calibrate components before authoring custom markup or CSS. Component props express layout, spacing, surface, typography, and interaction intent while keeping accessibility and brand defaults inside the system.

If a product need falls outside the component surface, keep the custom layer narrow: reuse Calibrate components for the pieces that fit, scope project CSS under .clbr, and use var(--clbr-*) tokens for design values.

Agents working in your repo can load the matching guardrails from @measured/calibrate-skills/compose-first and @measured/calibrate-skills/custom-with-tokens.

Configure linting

@measured/calibrate-config is the shared tooling package. It expects eslint and stylelint to be installed in your project.

ESLint

Layer the Calibrate preset onto your own flat config after the relevant baselines:

// eslint.config.mjs
import js from "@eslint/js";
import json from "@eslint/json";
import calibrateEslint from "@measured/calibrate-config/eslint";
import tseslint from "typescript-eslint";

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,
  ...json.configs.recommended,
  ...calibrateEslint,
  // project overrides
];

Calibrate’s ESLint config is additive: use it alongside the recommended configs for the languages and file types in your project, not as a standalone baseline.

Stylelint

Extend the shared config:

// .stylelintrc.mjs
export default {
  extends: ["@measured/calibrate-config/stylelint"],
};

This preset is intentionally opinionated. It enforces token discipline, logical CSS, and value restrictions that keep consumer CSS aligned with the design system.

If your project intentionally defines custom properties in one file and consumes them in another, opt into cross-file allowance:

export default {
  extends: ["@measured/calibrate-config/stylelint"],
  rules: {
    "calibrate/clbr-known-tokens": [true, { allowCrossFile: true }],
  },
};

Browserslist

Use Calibrate’s Browserslist query when configuring tools that accept query arrays:

import browserslist from "@measured/calibrate-config/browserslist";

For package.json, use the equivalent query:

{
  "browserslist": ["baseline widely available"]
}

For Vite or other esbuild-based tooling, use the esbuild target:

import target from "@measured/calibrate-config/browserslist/esbuild";

Configure CSS token variable autocomplete

@measured/calibrate-config/clbr.catalog.css exposes the published --clbr-* CSS custom property catalog for editor autocomplete.

For VS Code, copy it into .vscode/:

cp node_modules/@measured/calibrate-config/clbr.catalog.css .vscode/

Configure skills

Install the Calibrate skills package:

pnpm add -D @measured/calibrate-skills

Copy or symlink the shipped skill folders into your agent’s repo skills directory:

  • Claude Code: .claude/skills/
  • OpenAI Codex: .agents/skills/

Example:

cp -r node_modules/@measured/calibrate-skills/src/* .agents/skills/

The skills package is an experimental approach for carrying Calibrate’s composition, token, and voice rules into agent-assisted implementation work.

Use token data

Use @measured/calibrate-tokens when agents, docs, or local tooling need token artifacts as data rather than CSS. The public token entrypoints are:

import base from "@measured/calibrate-tokens/base";
import msrd from "@measured/calibrate-tokens/msrd";
import schema from "@measured/calibrate-tokens/schemas/v1";

That route is appropriate for agent context, docs, MCP tooling, design automation, schema validation, and downstream transforms.

Optional: render markdown content

If your app renders markdown, pair @measured/calibrate-markdown with the Prose component from core.

import { processMarkdown } from "@measured/calibrate-markdown";
import { renderClbrProse } from "@measured/calibrate-core";

const html = renderClbrProse({
  children: processMarkdown(markdown),
});

This keeps authored rich text aligned with the same typography and content styling as the rest of the system.