# Installation

## Choose an install path [#choose-an-install-path]

Each path uses the `uitheme-web` runtime. Pick one.

| Path                                  | Use it when                                                                      |
| ------------------------------------- | -------------------------------------------------------------------------------- |
| Runtime only                          | You build your own controls with the hooks. Any CSS works, Tailwind is optional. |
| [UI-Theme CLI](#install-with-the-cli) | You want ready controls in React or Vue, with Tailwind 3.4 or 4.                 |
| [shadcn](#install-with-shadcn)        | Your React app already uses shadcn with Tailwind 4.                              |

For the runtime only, install the package and add the provider for your
framework:

```sh
npm install uitheme-web@latest
```

The runtime changes theme classes and CSS variables. Supply your own styles.
The CLI and shadcn copy editable [controls](/docs/components) into your app.
The CLI requires an existing Tailwind setup. It does not create an app or
upgrade Tailwind.

## React [#react]

[Follow the React guide](/docs/guides/react).

```tsx
import { UIThemeProvider } from 'uitheme-web/react';

export function App() {
  return (
    <UIThemeProvider
      themes={['light', 'dark', 'system']}
      colorThemes={['default', 'caffeine']}
    >
      <YourApp />
    </UIThemeProvider>
  );
}
```

Read state and call actions with `useUITheme()` from `uitheme-web/react`.
`setTheme` and `setColorTheme` update immediately.
`switchTheme` and `switchColorTheme` use an animated transition.
Pass `{ element: event.currentTarget }` to anchor an animation to a control.
`theme` stores the preference. `resolvedTheme` reports light or dark after
resolving the system preference.

## Next.js App Router [#nextjs-app-router]

[Follow the Next.js guide](/docs/guides/nextjs).

Create a client provider wrapper.

```tsx title="app/providers.tsx"
'use client';

import { NextUIThemeProvider } from 'uitheme-web/next';

export function Providers({ children }: { children: React.ReactNode }) {
  return <NextUIThemeProvider>{children}</NextUIThemeProvider>;
}
```

Render `Providers` inside the root layout's body. Add `suppressHydrationWarning`
to the `html` element. The provider includes its pre-hydration bootstrap.
For a custom server bootstrap, import server-safe helpers from
`uitheme-web/next/server`. Keep browser hooks inside client components.

## TanStack Start [#tanstack-start]

[Follow the TanStack Start guide](/docs/guides/tanstack-start).

Use `TanStackUIThemeProvider` from `uitheme-web/react` for client state.
Use the stateless helpers from `uitheme-web/tanstack` to read server theme data
and build the initial HTML attributes and bootstrap script.
Create server data per request. Pass matching initial state to the provider.
Connect theme and palette change callbacks to your cookie persistence.
Keep storage keys and available options identical on the server and client.

## Vue 3 [#vue-3]

[Follow the Vue guide](/docs/guides/vue).

```ts title="src/main.ts"
import { createApp } from 'vue';
import { createUITheme } from 'uitheme-web/vue';
import App from './App.vue';

createApp(App)
  .use(
    createUITheme({
      defaultTheme: 'system',
      colorThemes: ['default', 'caffeine'],
    })
  )
  .mount('#app');
```

Use `useUITheme()` from `uitheme-web/vue` in setup.
A `UIThemeProvider` can define a separate scope.
For server rendering, create a fresh app and plugin for each request.
Use `getThemeScript` from `uitheme-web/vue/bootstrap` before hydration.
Do not share a provider or a theme store between requests.

## Nuxt 4 [#nuxt-4]

[Follow the Nuxt guide](/docs/guides/nuxt).

```ts title="nuxt.config.ts"
export default defineNuxtConfig({
  modules: ['uitheme-web/nuxt'],
  uiTheme: {
    defaultTheme: 'system',
    colorThemes: ['default', 'caffeine'],
  },
});
```

The module configures the Vue plugin, server bootstrap, and cookie persistence.
Use `useUITheme()` or import it from `uitheme-web/vue`.
Automatic setup supports Nuxt 4. The CLI rejects Nuxt 3 before changing files.

## Tailwind and palettes [#tailwind-and-palettes]

Use the dark variant for the `.dark` class in your Tailwind configuration.
For Tailwind 4, this can be defined in your CSS:

```css
@custom-variant dark (&:where(.dark, .dark *));
```

For Tailwind 3.4, set `darkMode: 'class'` in the Tailwind configuration.
Keep the existing content paths and include the directory for installed controls.
Define the semantic tokens used by controls, including `background`, `foreground`,
`primary`, `accent`, `muted`, `border`, `input`, `ring`, and `popover`, with their
foreground counterparts. Palette classes use the `theme-` prefix by default.

The CLI supports complete CSS colors and HSL channel tokens.
Review the dry-run before applying CSS changes. Existing imports, variables,
and plugins must remain intact.

## Without Tailwind [#without-tailwind]

The runtime works with any CSS. It adds the `dark` class to the `html` element
for the dark appearance. It also adds a `theme-<key>` class for the selected
palette, for example `theme-ocean`. Register each palette key in `colorThemes`
on the provider. Then define your variables for these classes:

```css title="styles.css"
:root {
  --background: #ffffff;
  --foreground: #0a0a0a;
}

.dark {
  --background: #0a0a0a;
  --foreground: #fafafa;
}

.theme-ocean {
  --background: #f0f9ff;
}

.theme-ocean.dark {
  --background: #082f49;
}

body {
  background: var(--background);
  color: var(--foreground);
}
```

The CLI and shadcn controls use Tailwind classes. Without Tailwind, build your
controls with `useUITheme()`.

## Install with the CLI [#install-with-the-cli]

Use the [component catalog](/docs/components) to choose a control. The CLI copies
editable source into your app. Set up the runtime, provider, and Tailwind first.
React supports Base UI (the default) and Radix. Vue supports Reka only.
Each installed component uses one base. It does not switch bases at runtime.

```sh
npx uitheme-cli init
npx uitheme-cli add theme-toggle --base base-ui
```

See the [CLI guide](/docs/cli) for commands, flags, workspace paths, and previews.
Review the plan before you replace edited component files.

## Install with shadcn [#install-with-shadcn]

Use this path in a React app that already has shadcn and Tailwind 4.

1. Add the UI-Theme registry to `components.json`:

   ```json title="components.json"
   {
     "registries": {
       "@uitheme": "https://www.ui-theme.dev/r/{style}/{name}.json"
     }
   }
   ```

2. Add a control:

   ```sh
   npx shadcn@latest add @uitheme/theme-toggle
   ```

3. Add the provider for your framework, as the sections above show. shadcn
   installs `uitheme-web`, but it does not add the provider.

The `style` in `components.json` selects the primitive base:

| Styles                                              | Base    |
| --------------------------------------------------- | ------- |
| `radix-*`, `new-york`, `new-york-v4`, and `default` | Radix   |
| `base-*`                                            | Base UI |

The registry serves Tailwind 4 source only. React Aria styles (`aria-*`) are
not supported. For Vue or Tailwind 3.4, use the
[UI-Theme CLI](#install-with-the-cli).

shadcn does not write `uitheme.json`, so `uitheme-cli diff` does not track the
files that shadcn installs.

## Native applications [#native-applications]

For Expo and React Native, install `uitheme-rn`. Follow the [Expo guide](/docs/guides/expo), [NativeWind guide](/docs/guides/nativewind), or [Uniwind guide](/docs/guides/uniwind). Each guide links to its example application.
