Skip to content

Nuxt 3

@theme-kit/nuxt

ModuleSSRZero-flashAuto-import

Nuxt 3 module with SSR-first theming, zero-flash bootstrap, cookie sync, config-driven transitions, custom scrollbar, and auto-imported composables.

Installation

Install the package for your framework alongside @theme-kit/core.

bash
pnpm add @theme-kit/nuxt

Quick Start

Start from scratch — install the package, then wrap your app in the provider at the entry point shown below.

nuxt.config.ts
ts
1import { themes } from "./themes";
2
3export default defineNuxtConfig({
4  modules: ["@theme-kit/nuxt"],
5  themeKit: {
6    themes,
7    defaultTheme: "mint-light",
8    initialMode: "system",
9    transition: { duration: 360, easing: "cubic-bezier(0.4, 0, 0.2, 1)" },
10    scrollbar: true,
11  },
12});
Every integration re-exports the full @theme-kit/core surface, so history, batching, snapshots, packs and lifecycle work the same way across frameworks.

Implementation

Read and update theme state from any component using the framework-native primitives below.

nuxt.config.ts
ts
1export default defineNuxtConfig({
2  modules: ["@theme-kit/nuxt"],
3  themeKit: {
4    themes,
5    defaultTheme: "mint-light",
6    initialMode: "system",
7  },
8});

What's Available

@theme-kit/nuxt ships 12 exports in 4 categories. Everything below is also documented in the full API reference. Click any export to reveal what it does and how to use it.

Server

Client

Transition

Scrollbar

Use Cases

The important features in practice — copy any of these straight into your app.

Add the module

Register the module and configure themes in nuxt.config.

Add the module
ts
1// nuxt.config.ts
2export default defineNuxtConfig({
3  modules: ["@theme-kit/nuxt"],
4  themeKit: {
5    themes,
6    defaultTheme: "mint-light",
7    initialMode: "system",
8  },
9});

SSR-first theming

Cookies are validated (fingerprint) and the initial theme is resolved and rendered server-side with a blocking bootstrap — no flash of the wrong theme.

SSR-first theming
ts
1// nuxt.config.ts
2export default defineNuxtConfig({
3  modules: ["@theme-kit/nuxt"],
4  themeKit: {
5    themes,
6    defaultTheme: "mint-light",
7    initialMode: "system",
8    initialFamily: "mint",
9  },
10});
11
12// The module emits, before first paint:
13//   <html data-theme="mint-light" data-theme-mode="light" data-theme-family="mint">
14//   <style>:root{--background:…}</style>
15//   <script>/* blocking bootstrap */</script>

Auto-imported composables

useTheme and friends are auto-imported in every component.

Auto-imported composables
vue
1<script setup>
2const { theme, mode, setMode, toggleTheme } = useTheme();
3</script>
4
5<template>
6  <button @click="toggleTheme">{{ theme.name }} · {{ mode }}</button>
7  <button @click="setMode('dark')">Dark</button>
8</template>

Components + runtime access

ThemeScope, ThemeScrollbar and the runtime are available everywhere.

Components + runtime access
vue
1<script setup>
2const runtime = useThemeRuntime();
3function soften() {
4  runtime.update({ radius: { sm: 8, md: 12 } });
5}
6</script>
7
8<template>
9  <ThemeScope theme="forest-light">
10    <DataViz />
11  </ThemeScope>
12  <ThemeScrollbar auto-hide />
13  <button @click="soften">Soften corners</button>
14</template>

Runtime access in a plugin

The plugin-provided runtime is available as `nuxtApp.$themeKit`.

Runtime access in a plugin
ts
1// plugins/theme.client.ts
2export default defineNuxtPlugin((nuxtApp) => {
3  const runtime = nuxtApp.$themeKit as ThemeRuntime;
4  runtime.lifecycle.on("beforeThemeChange", (e) => {
5    console.log("theme changed to", e.next.name);
6  });
7});

Smooth theme transitions

Enable config-driven CSS transitions on theme changes.

Smooth theme transitions
ts
1// nuxt.config.ts
2export default defineNuxtConfig({
3  modules: ["@theme-kit/nuxt"],
4  themeKit: {
5    themes,
6    defaultTheme: "light",
7    transition: { enabled: true, duration: 360, easing: "cubic-bezier(0.4, 0, 0.2, 1)" },
8  },
9});

More Examples

Scoped theming, history controls, and framework-specific patterns.

config + components
vue
1// nuxt.config.ts
2export default defineNuxtConfig({
3  modules: ["@theme-kit/nuxt"],
4  themeKit: {
5    themes,
6    defaultTheme: "mint-light",
7    initialMode: "system",
8    initialFamily: "mint",
9    transition: { duration: 300, easing: "ease" },
10    scrollbar: true,
11  },
12});
13
14// components/ThemeSwitcher.vue
15<script setup>
16// useTheme, useThemeRuntime, ThemeScope and ThemeScrollbar
17// are auto-imported by the module — no imports needed.
18const { theme, mode, family, setMode, setFamily, toggleTheme } = useTheme();
19</script>
20
21<template>
22  <button @click="toggleTheme">Toggle</button>
23  <button @click="setFamily('forest')">Forest</button>
24
25  <ThemeScope theme="forest-light">
26    <p>Scoped to forest-light</p>
27  </ThemeScope>
28
29  <ThemeScrollbar auto-hide />
30</template>

API Reference

Server

ExportDescription
SSR-first theme resolutionReads `theme-name`, `theme-mode`, `theme-family`, `theme-fingerprint` cookies, validates the fingerprint, resolves the initial theme, and renders `<html data-theme>` with inline CSS variables before hydration.
Blocking bootstrap scriptEmits a blocking script in `<head>` that applies the persisted theme before first paint.
Dark-mode CSS fallbackEmits `@media (prefers-color-scheme: dark)` styles when the persisted mode is `system`.
Cookie + localStorage syncThe client mirrors selection back to cookies so the server renders the right theme on the next request — same contract as `@theme-kit/next`.

Client

ExportDescription
Runtime pluginA Nuxt plugin installs one app-wide runtime, provided to `useTheme()`, `useThemeRuntime()` and every auto-imported composable.
Auto-importsComposables (`useTheme`, `useThemeMode`, `useThemeFamily`, `useThemeHistory`, …) and components (`ThemeScope`, `ThemeScrollbar`) are registered automatically — no manual imports.
configKey: "themeKit"Configure `themes`, `defaultTheme`, `initialMode`, `initialFamily`, `transition`, `scrollbar`, `storageKey` and `scheduled` in `nuxt.config.ts`.
useThemeSchedule()Auto-imported composable exposing the sunrise/sunset schedule: reactive `state` (`enabled`, `status`, `sunrise`, `sunset`, `nextTransition`) plus `enable()`/`disable()`/`set()`. Configure via `scheduled` in the module config.

Transition

ExportDescription
transition in nuxt.config.tsConfigure `transition` in the `themeKit` config object to enable CSS transitions on theme changes. Duration/easing are set once; Theme Kit generates the transition styles at runtime.
runtime.store.set(theme, { suppressTransition: true })Per-update escape hatch: `runtime.store.set(theme, { suppressTransition: true })` skips the configured animation. For custom animation orchestration, compose the core diff/plan/runner APIs.

Scrollbar

ExportDescription
scrollbar: trueEnables Theme Kit's custom overlay scrollbar. The SSR bootstrap hides the native scrollbar before first paint, then the overlay engine synchronizes with browser scrolling without replacing native scroll behavior.
scrollbar optionConfigure the overlay appearance (thickness, radius, colors, auto-hide, …) from the `themeKit` config; the overlay stays theme-aware and updates with runtime theme changes.
Nuxt 3 — Theme Kit