> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livry.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrating Livry with Chakra UI v3

> Build a Chakra v3 system whose token values are Livry custom properties, so every component rebrands when the stylesheet changes.

Chakra v3 accepts `var()` anywhere it takes a token value. So a Chakra system whose values are
Livry's custom properties rebrands entirely when the stylesheet changes — no provider swap, no
re-render.

**Theme integration required:** a pair whose library is `Chakra UI`. It builds `tokens.css`.

## 1. Link the stylesheet

```html theme={null}
<link id="livry" rel="stylesheet"
      href="https://cdn.livry.dev/{environmentID}/{themeID}/{variantID}/latest/tokens.css">
```

## 2. Build the system

```ts theme={null}
// theme.ts — every value is var(--livry-name, fallback), never the value itself.
import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react";

const config = defineConfig({
  theme: {
    tokens: {
      colors: {
        brand: {
          DEFAULT: { value: "var(--color-brand, #5B4DE4)" },
          primary: { value: "var(--color-brand-primary, #5B4DE4)" },
          hover:   { value: "var(--color-brand-hover, #4E3EC9)" },
        },
        surface: { value: "var(--color-surface, #FFFFFF)" },
      },
      spacing: {
        md: { value: "var(--space-md, 12px)" },
      },
      radii: {
        md: { value: "var(--radius-md, 6px)" },
      },
      fonts: {
        body: { value: "var(--font-body, system-ui)" },
      },
    },
  },
});

export const system = createSystem(defaultConfig, config);
```

<Note>
  **`DEFAULT` is how a token can be both a value and a group.** `color.brand` and `color.brand.500`
  both exist in plenty of token sets, and a JavaScript object cannot hold a value and children under
  one name. `DEFAULT` is Chakra v3's own spelling for exactly that — `colors.brand.DEFAULT` is
  addressed as `brand`.
</Note>

## 3. Wrap your app

<CodeGroup>
  ```tsx React theme={null}
  // main.tsx
  import { ChakraProvider } from "@chakra-ui/react";

  import { system } from "./theme";

  createRoot(document.getElementById("root")!).render(
    <ChakraProvider value={system}>
      <App />
    </ChakraProvider>,
  );
  ```

  ```tsx Next.js theme={null}
  // app/providers.tsx — a client component, because ChakraProvider uses context.
  // Wrap {children} in app/layout.tsx with <Providers>.
  "use client";

  import { ChakraProvider } from "@chakra-ui/react";

  import { system } from "./theme";

  export const Providers = ({ children }: { children: React.ReactNode }) => (
    <ChakraProvider value={system}>{children}</ChakraProvider>
  );
  ```
</CodeGroup>

## 4. Use Chakra normally

```tsx theme={null}
import { Button } from "@chakra-ui/react";

export const Save = () => (
  <Button bg="brand.primary" _hover={{ bg: "brand.hover" }} rounded="md" px="md">
    Save
  </Button>
);
```

Nothing names a colour. Swap the stylesheet and every Chakra component restyles — the provider and
the system are unchanged, because they never held a value in the first place.

## Generate it

The portal's **Integration** tab generates the whole `theme.ts` from your actual Theme: your tokens,
categorised into Chakra's token groups, with `var()` values and your real fallbacks.

Copy it once and edit freely. Which Chakra token each variable becomes is your naming decision, and
Livry only guessed — but it **stays right for every Variant**, because a Variant changes values and
never names.

## Semantic tokens

Chakra's semantic tokens work as usual, and they compose well with Livry: keep the raw values
pointing at Livry, and express meaning on top.

```ts theme={null}
semanticTokens: {
  colors: {
    "bg.canvas":  { value: "{colors.surface}" },
    "fg.accent":  { value: "{colors.brand.primary}" },
  },
}
```

<Note>
  Decide where meaning lives. Either model semantics **in Livry** as aliases — `color.fg.accent`
  aliasing `color.brand` — so a brand can override the semantic layer, or model them **in Chakra** as
  above, so they are fixed across brands. The first is more flexible; the second is more predictable.
  Doing both in the same theme gets confusing quickly.
</Note>

## Dark mode

Chakra's `_dark` conditions work unchanged, because they select on the DOM rather than on token
values. Point each side at its own Livry token:

```ts theme={null}
colors: {
  surface: {
    value: { base: "var(--color-surface-light, #fff)", _dark: "var(--color-surface-dark, #111)" },
  },
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.