Skip to content

Design system

The design system lives in apps/design/ and uses Ladle — a Vite-native, lightweight alternative to Storybook.

There is one shared design system used by every app. Tokens (colors, fonts) live in @mars/ui and are consumed by every app and by the design system itself, so changing a token updates everything.

Tokens are defined as Tailwind v4 @theme variables in packages/ui/src/theme.css:

@theme {
--color-background: #000;
--color-surface: oklch(0.18 0 0);
--color-foreground: #fff;
--color-accent: oklch(0.7 0.18 50);
/* ... */
}

Each variable generates utility classes. --color-accentbg-accent, text-accent, border-accent, etc.

Every app’s styles.css imports the theme:

@import 'tailwindcss';
@import '@mars/ui/theme.css';

Change a token once, every app picks it up on next reload.

Terminal window
pnpm dev --filter design

Opens at http://localhost:3100.

apps/design/src/
├── tokens/
│ ├── colors.stories.tsx
│ ├── typography.stories.tsx
│ └── spacing.stories.tsx
└── components/
└── Button.stories.tsx

Folders become sidebar groups. Each *.stories.tsx file becomes a sidebar entry. Each named export from a story file becomes one story.

Stories are plain React components, no special API needed:

export const MyVariant = () => <button className="...">Click me</button>
  1. Drop the story file in the matching folder (tokens/ or components/).
  2. Ladle hot-reloads.

That’s it.