# Getting Started

Get up and running with Tempo Design System, from install to your first component.

## Overview

Build consistent interfaces across Tempo products. Tempo Design System defines a shared design language, and `@tempoxyz/ds` delivers it as components and variables for web and React Native.

The library's APIs are deliberately constrained, so you build within the design system's rules. Zyzz compiles the components and your own styles ahead of time for your platform.

## Agent Prompt

Paste this prompt into your coding agent:

Read ds.tehq.dev and help me build my project with Tempo Design System.

## Setup

### Install the Library

Install `@tempoxyz/ds` and its Zyzz peer with your package manager.

```sh
npm install @tempoxyz/ds zyzz
```

### Choose Framework

Choose a compilation target and variable mode. TDS Variables (Quick) uses the components and variables as they ship. Custom Variables (Advanced) extends the TDS variables with app tokens.

### Vite

### Configure Vite

Add Zyzz alongside the existing framework plugin in `vite.config.ts`.

```ts title="vite.config.ts"
import { defineConfig } from 'vite'
import { zyzz } from 'zyzz/vite'

export default defineConfig({
  plugins: [zyzz()],
  ssr: { noExternal: ['@tempoxyz/ds', 'zyzz'] },
})
```

Run the project's existing dev or build command. The plugin emits the TDS variables, Pilat fonts, and keyframes once, and each component brings its own rules. There is no stylesheet to import. `ssr.noExternal` lets the plugin read the library's contracts in a server build.

#### TDS Variables (Quick)

### Use a Component

Import components from `@tempoxyz/ds`, and style your own markup with TDS tokens through `style`.

```tsx title="Checkout.tsx"
import { Button, style } from '@tempoxyz/ds'

export function Checkout() {
  return (
    <section {...styles.card()}>
      <p>Ready to continue?</p>
      <Button>Continue</Button>
    </section>
  )
}

namespace styles {
  export const card = style({
    backgroundColor: 'background.surface',
    borderRadius: 'lg',
    color: 'foreground',
    padding: '6',
    typography: 'copy.14',
  })
}
```

Tokens such as `foreground`, `'6'`, and `copy.14` type-check against the TDS variables. Light and dark values follow the inherited `color-scheme`.

#### Custom Variables (Advanced)

### Define Config

Extend the TDS variables with your app's tokens and export the bound styling helpers.

```ts title="zyzz.config.ts"
import { variables } from '@tempoxyz/ds'
import { Config, Vars } from 'zyzz'

export const { style, vars } = Config.create({
  id: 'app',
  vars: Vars.extend(variables, { spacing: { bleed: '-0.75rem' } }, { id: 'app/vars' }),
})
```

The Vite plugin scans the directory that holds `zyzz.config.ts` for global styles, so place it at the root of the application's source, such as `src/zyzz.config.ts`.

### Use a Component

Apply your config's `vars()` to the app root, beside the library's variables. Then style your markup with the bound `style` helper, mixing TDS and app tokens.

```tsx title="Checkout.tsx"
import { Button } from '@tempoxyz/ds'
import { style, vars } from './zyzz.config.js'

export function App() {
  return (
    <main {...vars()}>
      <Checkout />
    </main>
  )
}

function Checkout() {
  return (
    <section {...styles.card()}>
      <p>Ready to continue?</p>
      <Button>Continue</Button>
    </section>
  )
}

namespace styles {
  export const card = style({
    backgroundColor: 'background.surface',
    color: 'foreground',
    marginInline: 'bleed',
    padding: '6',
  })
}
```

### Other Bundlers

### Configure the Bundler

Add the matching unplugin adapter to the existing bundler configuration. Retain the project's TypeScript and JSX transforms.

```ts title="rollup.config.ts"
import { zyzz } from 'zyzz/unplugin'

const plugins = [zyzz.rollup()]
// Use zyzz.webpack() or zyzz.esbuild() for those bundlers.
```

Load the emitted stylesheet and initialization script from the application document. Adjust paths to the deployment base.

```html title="index.html"
<link rel="stylesheet" href="/zyzz.css" />
<script src="/zyzz.js"></script>
```

Run the existing build command. See [Bundler Setup](https://zyzz.style/docs/api/unplugin) for each bundler's configuration.

#### TDS Variables (Quick)

### Use a Component

Import components from `@tempoxyz/ds`, and style your own markup with TDS tokens through `style`.

```tsx title="Checkout.tsx"
import { Button, style } from '@tempoxyz/ds'

export function Checkout() {
  return (
    <section {...styles.card()}>
      <p>Ready to continue?</p>
      <Button>Continue</Button>
    </section>
  )
}

namespace styles {
  export const card = style({
    backgroundColor: 'background.surface',
    borderRadius: 'lg',
    color: 'foreground',
    padding: '6',
    typography: 'copy.14',
  })
}
```

Tokens such as `foreground`, `'6'`, and `copy.14` type-check against the TDS variables. Light and dark values follow the inherited `color-scheme`.

#### Custom Variables (Advanced)

### Define Config

Extend the TDS variables with your app's tokens and export the bound styling helpers.

```ts title="zyzz.config.ts"
import { variables } from '@tempoxyz/ds'
import { Config, Vars } from 'zyzz'

export const { style, vars } = Config.create({
  id: 'app',
  vars: Vars.extend(variables, { spacing: { bleed: '-0.75rem' } }, { id: 'app/vars' }),
})
```

### Use a Component

Apply your config's `vars()` to the app root, beside the library's variables. Then style your markup with the bound `style` helper, mixing TDS and app tokens.

```tsx title="Checkout.tsx"
import { Button } from '@tempoxyz/ds'
import { style, vars } from './zyzz.config.js'

export function App() {
  return (
    <main {...vars()}>
      <Checkout />
    </main>
  )
}

function Checkout() {
  return (
    <section {...styles.card()}>
      <p>Ready to continue?</p>
      <Button>Continue</Button>
    </section>
  )
}

namespace styles {
  export const card = style({
    backgroundColor: 'background.surface',
    color: 'foreground',
    marginInline: 'bleed',
    padding: '6',
  })
}
```

### React Native

### Configure Metro

Install the React Native peers, then wrap the Expo Metro configuration with Zyzz. Preserve the existing transformer and Expo settings.

```sh
npx expo install expo-haptics react-native-reanimated react-native-svg react-native-worklets
```

```ts title="metro.config.ts"
import { getDefaultConfig } from 'expo/metro-config'
import { zyzz } from 'zyzz/metro'

export default zyzz(getDefaultConfig(import.meta.dirname), {
  fonts: { 'HB Set v0.96': 'HBSet', Inter: 'Inter', 'JetBrains Mono': 'JetBrainsMono' },
  units: { px: 1, rem: 16 },
})
```

`fonts` maps each Figma family to a font that your app registers. The library bundles no font files. Map a family to `System` to preview with iOS system fonts.

#### TDS Variables (Quick)

### Use a Component

Render components from `@tempoxyz/ds/mobile` below a `Provider` at the app root. Styles resolve against the Provider above the component that renders them.

```tsx title="App.tsx"
import { Button, Provider, style } from '@tempoxyz/ds/mobile'
import { Text, View } from 'react-native'

export function App() {
  return (
    <Provider colorScheme="system">
      <Checkout />
    </Provider>
  )
}

function Checkout() {
  return (
    <View {...styles.card()}>
      <Text {...styles.label()}>Ready to continue?</Text>
      <Button onPress={() => {}}>Continue</Button>
    </View>
  )
}

namespace styles {
  export const card = style({
    backgroundColor: 'background.elevated',
    gap: '12',
    paddingHorizontal: '20',
    paddingVertical: '16',
  })

  export const label = style({ color: 'content.primary', typography: 'body.b2' })
}
```

`colorScheme="system"` follows the device setting. Pass `light` or `dark` to override it.

#### Custom Variables (Advanced)

### Define Config

Define app tokens in sets named `base` and `inverse`, since every Zyzz config reads the Provider's set selection. Reference TDS values through `variables` and `inverse`.

```ts title="zyzz.config.ts"
import { inverse as tdsInverse, variables } from '@tempoxyz/ds/mobile'
import { Vars } from 'zyzz'
import { defineConfig } from 'zyzz/react-native'

export const base = Vars.define({
  color: {
    caption: { light: variables.color.content.secondary, dark: variables.color.content.secondary },
  },
})

export const inverse = Vars.extend(base, {
  color: {
    caption: {
      light: tdsInverse.color.content.secondary,
      dark: tdsInverse.color.content.secondary,
    },
  },
})

export const { style } = defineConfig({ defaultVars: 'base', id: 'app', vars: { base, inverse } })
```

Zyzz extensions only replace existing tokens, so app tokens live in your own sets rather than extending the TDS ones.

### Use a Component

Render TDS components below a `Provider`, and style your own elements with the bound `style` helper.

```tsx title="App.tsx"
import { Button, Provider } from '@tempoxyz/ds/mobile'
import { Text, View } from 'react-native'
import { style } from './zyzz.config.js'

export function App() {
  return (
    <Provider colorScheme="system">
      <View>
        <Text {...styles.caption()}>Ready to continue?</Text>
        <Button onPress={() => {}}>Continue</Button>
      </View>
    </Provider>
  )
}

namespace styles {
  export const caption = style({ color: 'caption' })
}
```

## Next Steps

[Build a Layout](/docs/components/app-shell)

Place a sticky sidebar beside the main content column.

[Trigger Actions](/docs/components/button)

Submit forms, send payments, and run other actions.

[Collect Input](/docs/components/field)

Link labels, descriptions, and errors to form controls.

[Show Feedback](/docs/components/toast)

Confirm results with brief notifications.
