> ## 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 Plain CSS

> Link tokens.css, reference the custom properties from your own stylesheets, and switch brands by changing one href.

The simplest integration, and the one every other guide is built on. It works with no framework, and
equally with shadcn/ui, Angular Material or Skeleton — anything that styles through CSS custom
properties.

**Theme integration required:** any pair whose library is `Plain CSS` (or Tailwind, Chakra UI,
shadcn/ui, Angular Material, Skeleton — they all build `tokens.css`).

## 1. Link the stylesheet

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

  <link rel="stylesheet" href="/app.css">
</head>
```

<Warning>
  **Livry first, your own stylesheets second.** Custom properties must be defined before the rules
  that reference them are evaluated, or the first paint uses your fallbacks and then flashes.
</Warning>

The file declares everything on `:root`:

```css theme={null}
/* Generated by Livry. Do not edit. */
:root {
  --color-brand-primary: #5B4DE4;
  --color-brand-hover: #5B4DE4;
  --space-md: 12px;
  --radius-md: 6px;
  --font-body: Inter, system-ui, sans-serif;
}
```

## 2. Reference, never copy

```css theme={null}
/* app.css */
.button {
  background: var(--color-brand-primary, #5B4DE4);
  padding: var(--space-md, 12px);
  border-radius: var(--radius-md, 6px);
  font-family: var(--font-body, system-ui);
}

.button:hover {
  background: var(--color-brand-hover, #5B4DE4);
}
```

<Note>
  **Always write the fallback.** The value after the comma is what the browser uses if the property
  is not defined — because the stylesheet failed to load, or because that token does not exist in
  this Theme yet. Use your Theme's own value, so the unbranded state is your default brand rather
  than nothing.
</Note>

## 3. Switch brands

```ts theme={null}
// livry.ts
const LIVRY_THEME = "https://cdn.livry.dev/{environmentID}/{themeID}";

/** The stylesheet for one variant (or the theme on its own) at one version. */
export const livryStylesheet = (variantID?: string, version: number | "latest" = "latest") =>
  `${LIVRY_THEME}/${variantID ?? "-"}/${version}/tokens.css`;

export const applyLivryVariant = (variantID?: string) => {
  const link = document.getElementById("livry") as HTMLLinkElement;
  link.href = livryStylesheet(variantID);
};
```

That is the whole brand-switching mechanism. **No re-render**, because nothing in your app holds a
value — the browser recomputes every `var()` when the stylesheet changes.

Pass `"-"` (or nothing) for the Theme with no Variant applied — your own default styling.

## Avoiding the flash on switch

Swapping an `href` makes the browser fetch before it repaints, so there is a brief moment with the
old brand. If that matters, preload the next one:

```ts theme={null}
export const preloadLivryVariant = (variantID: string) => {
  const link = document.createElement("link");
  link.rel = "preload";
  link.as = "style";
  link.href = livryStylesheet(variantID);
  document.head.append(link);
};
```

In a multi-tenant app you usually know the brand before the page loads — render the right `<link>`
server-side and never switch at all.

## Dark mode

Livry has no mode concept. Two approaches, both yours rather than Livry's:

<CodeGroup>
  ```css One theme, two token sets theme={null}
  .button {
    background: var(--color-surface-light, #fff);
  }

  @media (prefers-color-scheme: dark) {
    .button {
      background: var(--color-surface-dark, #111);
    }
  }
  ```

  ```ts Two Themes theme={null}
  // A separate Livry Theme per mode, each with its own Variants.
  export const livryStylesheet = (variantID: string, dark: boolean) =>
    `https://cdn.livry.dev/${ENV}/${dark ? THEME_DARK : THEME_LIGHT}/${variantID}/latest/tokens.css`;
  ```
</CodeGroup>

The first is simpler and keeps one Variant per brand. The second gives a brand genuinely independent
light and dark palettes.

## What is not in the file

`tokens.css` is a **lossy projection**. CSS has no token types, no groups and no descriptions, and
some DTCG values have no CSS spelling at all.

A token that cannot be written becomes a comment naming its path:

```css theme={null}
:root {
  --color-brand-primary: #5B4DE4;
  /* border.focus: no CSS spelling for this strokeStyle */
}
```

So you can diff the stylesheet against your token list and see exactly what is missing. If you need
the full fidelity, read `tokens.json` instead — see [What gets served](/serving/files).


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