Skip to content

Installation

Install the runtime, then add controls with the CLI or shadcn.

Choose an install path

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

PathUse it when
Runtime onlyYou build your own controls with the hooks. Any CSS works, Tailwind is optional.
UI-Theme CLIYou want ready controls in React or Vue, with Tailwind 3.4 or 4.
shadcnYour React app already uses shadcn with Tailwind 4.

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

npm install uitheme-web@latest

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

React

Follow the React guide.

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

Follow the Next.js guide.

Create a client provider wrapper.

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

Follow the TanStack Start guide.

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

Follow the Vue guide.

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

Follow the Nuxt guide.

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

Use the dark variant for the .dark class in your Tailwind configuration. For Tailwind 4, this can be defined in your 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

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:

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

Use the component catalog 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.

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

See the CLI guide for commands, flags, workspace paths, and previews. Review the plan before you replace edited component files.

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:

    components.json
    {
      "registries": {
        "@uitheme": "https://www.ui-theme.dev/r/{style}/{name}.json"
      }
    }
  2. Add a control:

    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:

StylesBase
radix-*, new-york, new-york-v4, and defaultRadix
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.

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

Native applications

For Expo and React Native, install uitheme-rn. Follow the Expo guide, NativeWind guide, or Uniwind guide. Each guide links to its example application.