# How to Customize the Theme Using Celeris Web's Theme Setting System

> Customize Celeris Web's theme easily with the Theme Setting system. Control colors, dark mode, and system preferences using the composable API for reactive updates.

- Repository: [Kirk Lin/celeris-web](https://github.com/kirklin/celeris-web)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Celeris Web centralizes all visual customization in a ThemeSetting object managed by the Pinia store useDesignStore, enabling reactive theme updates—including primary colors, dark mode toggles, and system preference tracking—through the useThemeSetting composable API.**

The open-source celeris-web repository provides a robust theme setting system built on Pinia and Naive UI. This architecture allows developers to programmatically control every aspect of the application's appearance through a centralized, reactive configuration layer that updates the UI without page reloads.

## Understanding the Theme Architecture

The theme setting system implements a five-layer architecture that separates default values, state management, public API abstractions, theme generation, and UI provider injection.

### 1. Default Configuration Layer

All theme defaults reside in `DEFAULT_THEME_SETTING` defined in [`apps/admin/src/setting/themeSetting.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/setting/themeSetting.ts). This object initializes the default states for gray mode, dark mode, system-follow behavior, primary color, and auxiliary color tokens.

### 2. State Management with Pinia

The `useDesignStore` in [`apps/admin/src/store/modules/design/index.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/store/modules/design/index.ts) maintains the `themeSetting` state and exposes type-safe getters such as `getDarkMode`, `getThemeColor`, `shouldEnableGrayMode`, and `shouldFollowSystemTheme`. The store uses `deepMerge` to apply partial updates without destroying existing configuration objects.

### 3. Public API via Composables

The `useThemeSetting` composable in [`apps/admin/src/composables/setting/useThemeSetting.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/composables/setting/useThemeSetting.ts) wraps the store with reactive `toRef` bindings. It exposes getter and setter pairs—including `getDarkMode`/`setDarkMode`, `getThemeColor`/`setThemeColor`, and `setFollowSystemTheme`—which serve as the primary interface for UI components.

### 4. Theme Generation Engine

When Naive UI requires concrete theme values, `getNaiveUICustomTheme` in [`apps/admin/src/store/modules/design/themeUtils.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/store/modules/design/themeUtils.ts) executes. This function builds color palettes via `generateColorPalettes` (which supports dark-mode awareness), merges them into Naive UI's `common` overrides, and applies component-specific fixes for button text, checkbox ticks, and other interactive elements.

### 5. Provider Injection

The `useNaiveUIConfigProvider` composable in [`apps/admin/src/composables/useNaiveUIConfigProvider.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/composables/useNaiveUIConfigProvider.ts) supplies the root `n-config-provider` with either `lightTheme` or `darkTheme` presets plus the custom overrides. This ensures all Naive UI components receive reactive theme updates prop-drilled from the application root.

## Customizing Theme Settings

Developers modify specific visual aspects through targeted API calls. Each change propagates reactively through the store to the UI without requiring navigation or refresh.

### Changing the Primary Color

Call `setThemeColor()` with a hex value, or modify `DEFAULT_THEME_SETTING.themeColor` directly. The [`themeUtils.ts`](https://github.com/kirklin/celeris-web/blob/main/themeUtils.ts) palette generator creates new light and dark color shades automatically and merges them into Naive UI's common overrides.

### Managing Dark Mode

Use `setDarkMode(boolean)` to toggle between themes. The `getDarkMode` getter determines which preset theme (`darkTheme` or `lightTheme`) the Config Provider passes to Naive UI components.

### Following System Preferences

Enable `setFollowSystemTheme(true)` to synchronize with OS dark-mode settings. The store monitors `usePreferredDark()` and automatically switches presets when system appearance preferences change.

### Configuring Auxiliary Colors

Extend `otherColor` tokens (info, success, warning, error) by calling `setThemeSetting({ otherColor: {...} })` or editing the default configuration. These values inject component-level overrides via `themeUtils.getOtherColor()`.

### Accessibility Modes

Toggle `shouldEnableGrayMode` or `shouldEnableColorWeak` via their respective setters. These boolean flags apply CSS classes to layout wrappers, enabling grayscale or high-contrast rendering for accessibility compliance.

## Implementation Examples

### Runtime Primary Color Updates

```typescript
import { useThemeSetting } from '~/composables/setting'

const { setThemeColor } = useThemeSetting()

function onColorPick(colorHex: string) {
  // Color picker returns '#1890ff' or similar
  setThemeColor(colorHex)
}

```

### Dark Mode Toggle

```typescript
import { useThemeSetting } from '~/composables/setting'

const { setDarkMode } = useThemeSetting()

// Handler for toggle switch
function toggleDark(checked: boolean) {
  setDarkMode(checked)
}

```

### System Theme Synchronization

```typescript
import { useThemeSetting } from '~/composables/setting'

const { setFollowSystemTheme } = useThemeSetting()

// Application now mirrors OS appearance settings
setFollowSystemTheme(true)

```

### Extending Color Palettes

```typescript
import { useThemeSetting } from '~/composables/setting'

const { setThemeSetting } = useThemeSetting()

setThemeSetting({
  otherColor: {
    info: '#2db7f5',
    success: '#52c41a',
    warning: '#faad14',
    error: '#f5222d',
  },
})

```

### App.vue Config Provider Setup

```vue
<script setup lang="ts">
import { useNaiveUIConfigProvider } from '~/composables/useNaiveUIConfigProvider'
const { configProviderProps } = useNaiveUIConfigProvider()
</script>

<template>
  <n-config-provider v-bind="configProviderProps">
    <router-view />
  </n-config-provider>
</template>

```

## Key Files in the Theme System

- [`apps/admin/src/setting/themeSetting.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/setting/themeSetting.ts) – Contains `DEFAULT_THEME_SETTING` with initial theme values
- [`apps/admin/src/store/modules/design/index.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/store/modules/design/index.ts) – Pinia store holding `themeSetting` state and `deepMerge` actions
- [`apps/admin/src/composables/setting/useThemeSetting.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/composables/setting/useThemeSetting.ts) – Public composable façade exposing reactive getters and setters
- [`apps/admin/src/store/modules/design/themeUtils.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/store/modules/design/themeUtils.ts) – Generates color palettes and Naive UI theme overrides
- [`apps/admin/src/composables/useNaiveUIConfigProvider.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/composables/useNaiveUIConfigProvider.ts) – Supplies the computed theme to Naive UI's provider
- [`packages/web/types/src/config.ts`](https://github.com/kirklin/celeris-web/blob/main/packages/web/types/src/config.ts) – TypeScript interface definitions for `ThemeSetting`

## Summary

- Theme customization centers on the **ThemeSetting** object managed by **useDesignStore**.
- The **useThemeSetting** composable provides the public API for reactive theme control with `toRef` bindings.
- **generateColorPalettes** in [`themeUtils.ts`](https://github.com/kirklin/celeris-web/blob/main/themeUtils.ts) creates dark-aware color scales automatically.
- All changes propagate immediately through Naive UI's ConfigProvider without page reloads.
- The system supports primary color customization, manual dark mode toggling, OS preference following, and auxiliary color token injection.

## Frequently Asked Questions

### Where are default theme values defined in Celeris Web?

Default theme values are defined in the `DEFAULT_THEME_SETTING` object located at [`apps/admin/src/setting/themeSetting.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/setting/themeSetting.ts). This file initializes all default states including the primary color, gray mode settings, and auxiliary color tokens for info, success, warning, and error states.

### How does the theme setting system handle dark mode switching?

The system uses the `getDarkMode` getter in `useDesignStore` to determine the active theme preset. When `setDarkMode` is called with a boolean value, the store updates its state, triggering `useNaiveUIConfigProvider` to switch between `lightTheme` and `darkTheme` presets and regenerate color palettes accordingly.

### Can the application automatically follow the operating system's dark mode preference?

Yes. Call `setFollowSystemTheme(true)` from the `useThemeSetting` composable. This enables the store to monitor `usePreferredDark()` and automatically toggle between light and dark themes based on the user's OS appearance settings without manual intervention.

### How do I add custom brand colors beyond the primary color?

Use the `setThemeSetting` method to update the `otherColor` property with custom hex values for info, success, warning, and error tokens. These values propagate through [`apps/admin/src/store/modules/design/themeUtils.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/store/modules/design/themeUtils.ts) to generate component-specific overrides that apply throughout the Naive UI component library.