Skip to content

Getting started

Two ways in: scaffold a new project, or add helix-ui to an app you already have.

Every snippet on this page is the same code the create-helix-ui-app templates ship, which CI scaffolds, installs, and compiles on every commit.

Requirements

  • Node 20 or newer
  • React 18 or 19 — both are supported peer ranges
  • A bundler that understands ESM and CSS imports (Vite, Next.js, Remix, Parcel, webpack 5). helix-ui ships ESM only.

What it costs you

Named imports tree-shake, so you pay for what you render. Measured gzipped, with react and react-dom treated as already present, each component bundled alone:

Importgzip
Button, Text, Card, Stack, Badge250–450 B each
TextInput, Switch, Checkbox11–14 kB
Dialog~18 kB
Select~57 kB
A typical form (TextInput + Checkbox + Select + Button)~60 kB
@helix-ui/tokens CSS~1.6 kB
One icon from @helix-ui/icons~380 B

The shape is worth understanding before you commit: the layout and visual primitives are almost free because they are CSS-driven markup with no behavior. The cost arrives with the first interactive component, which pulls in React Aria — that’s the price of the focus management, keyboard interaction, and ARIA wiring you’d otherwise write yourself. Select is the outlier; it brings the overlay, listbox, and collection machinery with it.

These numbers are enforced as budgets in CI (pnpm size), so they can’t drift silently.

Option A — start a new app

Terminal window
npm create helix-ui-app@latest my-app
cd my-app
npm run dev

The scaffolder asks which template you want and installs with whichever package manager you invoked it with:

TemplateWhat you get
minimalOne themed card and the DNA preset switcher. Start here.
adminSidebar, page header, stat cards, data table.
marketingHero, feature grid, pricing.
agent-uiChat shell with thinking blocks and tool calls.

Pick one non-interactively with --template:

Terminal window
npm create helix-ui-app@latest my-app -- --template admin

Option B — add to an existing app

Terminal window
npm install @helix-ui/core @helix-ui/tokens @helix-ui/dna @helix-ui/icons

@helix-ui/core needs @helix-ui/tokens and @helix-ui/dna, so a package manager will pull them in regardless — installing them explicitly just makes the dependency visible in your manifest. @helix-ui/icons is optional.

1. Import the stylesheet, once

At your app entry, before your own CSS:

main.tsx
import '@helix-ui/core/styles.css';

That’s the only import you need — styles.css already @imports @helix-ui/tokens/css, so the design tokens come with it.

Skip it and every component renders as a plain browser default: component CSS references var(--helix-ui-…) with no fallbacks, so with no stylesheet loaded those declarations are simply invalid. In development helix-ui notices and tells you in the console; in production it says nothing, so keep the import.

What that stylesheet will and won’t do to your app

Dropping a component library into an app that already has styles is usually the risky part, so this is explicit:

  • It only styles its own elements. Every rule is scoped to a helix-ui-* class. Nothing selects body, *, button, a, or any element your app owns — importing helix-ui cannot change how your existing markup renders.
  • It ships no global reset. Your margins, your typography, your box model stay exactly as they were.
  • It doesn’t depend on your reset either. helix-ui applies box-sizing: border-box to its own elements, so components size correctly whether or not your app has a reset of its own.
  • The one shared hook is data-theme. helix-ui reads data-theme="light" / "dark" to pick its token set, so if your app already toggles that attribute, helix-ui follows your theme automatically. It only ever defines --helix-ui-* variables there — it never restyles your elements.

helix-ui does not use CSS @layer, so its rules compete on normal specificity. Most are a single class (0,1,0), so your own class targeting the same element wins by source order or a slightly more specific selector — no !important needed.

Importing the tokens on their own is also fine if you want the CSS variables without any components:

import '@helix-ui/tokens/css';

2. Wrap your tree in a DNA provider

import { HelixUIDNAProvider } from '@helix-ui/core';
import { wildtype } from '@helix-ui/dna';
export function App() {
return <HelixUIDNAProvider dna={wildtype()}>{/* your app */}</HelixUIDNAProvider>;
}

wildtype() is the default genome. The provider resolves it into CSS variables on a wrapper element, so everything below re-themes through the cascade — no context reads, no re-renders.

3. Render something

import { Button, Card, Stack, Text } from '@helix-ui/core';
import { Sparkle } from '@helix-ui/icons';
<Card variant="elevated" style={{ padding: 'var(--helix-ui-space-8)' }}>
<Stack gap={5}>
<Stack direction="row" gap={3} align="center">
<Sparkle />
<Text size="2xl" weight="semibold">
Hello, helix-ui.
</Text>
</Stack>
<Button tone="brand">Ship it</Button>
</Stack>
</Card>;

That’s the whole setup. Everything else on this site is detail.

Change the theme

Swap the genome and the tree follows. The five built-in presets:

import { PRESETS, wildtype } from '@helix-ui/dna';
<HelixUIDNAProvider dna={PRESETS.noir()}></HelixUIDNAProvider>;

wildtype · studio · botanic · solstice · noir.

To go further than a preset, breed one:

Terminal window
npx @helix-ui/dna breed studio noir --seed 42 --output shorthand

Pass the resulting mutations array to the provider. See DNA for the gene model.

Framework notes

Next.js App Router — every helix-ui component carries 'use client', so importing one from a server component works without extra wrapping. Import the stylesheets in app/layout.tsx. See React Server Components.

Components also hydrate cleanly: nothing renders from Math.random(), from the viewport, or from document on the first pass, so the browser reproduces the server’s HTML instead of replacing it. Components that do care about the viewport or the current theme — Chart, CodeEditor — render the server’s answer while hydrating and pick up the real one immediately after. A test renders the library in Node and hydrates it in a real browser on every CI run, so this stays true.

Tailwind — helix-ui tokens are available as a Tailwind preset, so utilities and components share one scale rather than drifting. See Tailwind.

TypeScript — every package you import from ships its own declarations (@helix-ui/core, tokens, dna, icons, document, slides); no @types/* needed. The spec.md beside each component is the same API surface the types express. The CLI-only packages (@helix-ui/mcp, @helix-ui/prompt, @helix-ui/stylelint-plugin) are plain JS — you run them, you don’t import them.

Point your AI tools at it

helix-ui is built to be read by a model as easily as by a person:

Terminal window
claude mcp add helix-ui -- npx -y @helix-ui/mcp

Or hand any assistant a single URL: llms.txt for the index, llms-full.txt for everything. See Integrations for Cursor, Copilot, Windsurf, and a tool-agnostic AGENTS.md.

Where to next

  • Components — every component’s props, tokens, and a11y contract.
  • Tokens overview — how the DTCG JSON becomes CSS variables.
  • DNA — the 22-gene theme model.
  • Compatibility — exact versions helix-ui is tested against.