Skip to main content

Theme Settings

Theme settings are typically applied like this:
  1. Define defaults in theme.config.ts
  2. Fetch published overrides for a shop
  3. Merge overrides into defaults
  4. Apply settings to your UI (often via CSS variables)
Your theme decides how to apply settings. A common approach is CSS variables so the whole UI updates consistently.

Defaults + Published Overrides

This example uses helpers from @shoppexio/storefront:
// @validate
import shoppex, {
  fetchPublishedThemeSettings,
  mergeSettings,
  resolveDefaults,
  type ThemeConfig,
} from '@shoppexio/storefront';

const themeConfig = {
  id: 'my-theme',
  name: 'My Theme',
  version: '1.0.0',
  settings: {
    colors: {
      primary: { type: 'color', label: 'Primary', default: '#7c3aed' },
    },
  },
  sections: {},
} satisfies ThemeConfig;

shoppex.init('my-shop', { apiBaseUrl: 'https://api.shoppex.io' });

const defaults = resolveDefaults(themeConfig);
const published = await fetchPublishedThemeSettings('my-shop');
const settings = published ? mergeSettings(defaults, published) : defaults;

console.log(settings.colors.primary);

Apply A Setting

If you use CSS variables, you can apply a color like this:
// @validate
const primary = '#7c3aed';
document.documentElement.style.setProperty('--color-primary', primary);

CSS Variable Mapping (Reference Theme)

The reference theme maps settings to CSS variables as follows. Your theme can use different variable names — this is just how the built-in default theme does it.
Setting PathCSS VariableTransform
colors.background--surfacehexToRgb
colors.surface--card-bghexToRgb
colors.primary--brand-600hexToRgb
colors.primaryDark--brand-700hexToRgb (fallback: colors.secondary, then darken primary 10%)
colors.text--texthexToRgb
colors.textMuted--text-mutedhexToRgb
colors.textContrast--text-contrasthexToRgb
colors.border--borderhexToRgb
colors.muted--mutedhexToRgb
colors.accent--accenthexToRgb
colors.hover--hoverhexToRgb
colors.success--successhexToRgb
colors.error--destructivehexToRgb
typography.fontFamily--font-family-bodydirect string (also fallback for --font-family-heading)
typography.headingFont--font-family-headingdirect string (falls back to typography.fontFamily)
typography.fontSize--font-size-baseappend px
effects.borderRadius--radiusvalue / 16 + rem
buttons.borderRadius--button-radiusappend px
header.height--header-heightappend px
inputs.height--input-heightappend px
inputs.borderRadius--input-border-radiusappend px
This mapping is from the reference theme. Your theme can use different variable names.

Next Steps

Build Pipeline

How settings can be injected as initial data during build (optional).

React Reference

See a full working theme in this repo.

Sources

Reference implementation:
  • themes/default/src/context/ThemeSettingsContext.tsx
  • themes/default/src/lib/cssVars.ts