storefront-theming
Build a themeable storefront with design tokens and CSS custom properties that supports white-labeling, multi-brand variants, and dark mode
What this skill does
# Storefront Theming
## Overview
Architect a theming system using design tokens and CSS custom properties that allows a storefront to be re-skinned for multiple brands without modifying component code. Covers the token taxonomy (color, typography, spacing, radius), runtime theme switching for dark mode, and white-label multi-tenant architecture where each tenant supplies their own token overrides.
## When to Use This Skill
- When building a platform that will power multiple branded storefronts from a single codebase
- When implementing dark mode for a storefront
- When a rebrand requires changing colors across thousands of component instances without hunt-and-replace
- When handing off a design system to a team that needs to maintain brand consistency
## Core Instructions
### Step 1: Determine the merchant's platform and choose the right approach
| Platform | Recommended Approach | Why |
|----------|---------------------|-----|
| **Shopify** | Use the Theme Editor's **Color scheme** system + edit `config/settings_schema.json` and `assets/base.css` to add custom CSS variables | Shopify OS2.0 themes expose all brand colors, fonts, and border radii as Theme Editor settings that write to CSS variables automatically; no build step required |
| **WooCommerce** | Use the WordPress **Global Styles** system (WordPress 5.9+) with a block theme, or configure CSS variables in **Appearance → Customize → Additional CSS** for classic themes | Block themes using `theme.json` support a full design token system natively; classic themes need CSS custom properties added manually |
| **BigCommerce** | Configure theme settings in **Storefront → My Themes → Customize** — Cornerstone exposes colors, fonts, and spacing as Theme Editor variables; advanced customization via `config.json` and SCSS | Cornerstone compiles SCSS with Handlebars template variables; custom CSS variables can be added to the global stylesheet |
| **Custom / Headless** | Build a three-tier token system (global → semantic → component) using CSS custom properties, compiled from JSON using Style Dictionary | Full control over token taxonomy, dark mode, and multi-tenant overrides; see implementation below |
### Step 2: Configure theming on your platform
---
#### Shopify
**Using the Theme Editor color system (no code required):**
1. Go to **Online Store → Themes → Customize**
2. Click **Theme settings** (paint bucket icon) in the left panel
3. Under **Colors**, configure your brand's:
- Primary, secondary, and accent colors
- Background colors
- Text colors
- Button colors and text
4. Under **Typography**, set your font families and sizes
5. Under **Buttons and inputs**, configure border radius for buttons and form fields
6. All changes write to CSS custom properties that every component in the theme uses — no component-level changes needed
**Adding custom CSS variables (for developers extending the theme):**
1. Go to **Online Store → Themes → Edit code**
2. Open `assets/base.css` (Dawn) or equivalent
3. Add your custom variables to the `:root` block, referencing the theme's settings variables:
```css
:root {
--color-button: {{ settings.color_button.red }}, {{ settings.color_button.green }}, {{ settings.color_button.blue }};
--font-body-family: {{ settings.type_body_font.family }}, sans-serif;
}
```
4. In your section/component Liquid files, use `var(--color-button)` to reference the merchant-controlled setting
---
#### WooCommerce
**Block themes with theme.json (WordPress 5.9+):**
If you're building a new store with a block theme (like Storefront Blocks or a custom block theme):
1. Open `theme.json` in your theme root
2. Add your design tokens to the `settings.color.palette` and `settings.typography` sections:
```json
{
"settings": {
"color": {
"palette": [
{ "slug": "brand-primary", "color": "#2563eb", "name": "Brand Primary" },
{ "slug": "brand-secondary", "color": "#3b82f6", "name": "Brand Secondary" }
]
},
"custom": {
"spacing": { "xs": "0.5rem", "sm": "1rem", "md": "1.5rem" }
}
}
}
```
3. WordPress automatically exposes these in the **Global Styles** panel and generates CSS custom properties like `--wp--preset--color--brand-primary`
**Classic themes — CSS variables in Additional CSS:**
1. Go to **Appearance → Customize → Additional CSS**
2. Define your brand variables:
```css
:root {
--color-primary: #2563eb;
--color-price-sale: #dc2626;
--font-size-base: 1rem;
--border-radius-button: 0.375rem;
}
```
3. Use these variables in your child theme's CSS instead of hard-coded values
---
#### BigCommerce
**Cornerstone theme variables (SCSS-based):**
1. Go to **Storefront → My Themes → Edit Theme Files** (requires a copy of the theme)
2. Open `assets/scss/settings/global/` — Cornerstone organizes variables by category (color, typography, spacing)
3. Modify `_color.scss` to update the brand color palette
4. Open `config.json` in the theme root — this maps Theme Editor controls to SCSS variables:
```json
{
"settings": {
"color-primary": "#2563eb",
"font-size-root": "16px",
"button-radius": "4px"
}
}
```
5. In **Storefront → My Themes → Customize**, the Theme Editor reflects these settings for merchant configuration
---
#### Custom / Headless
**Three-tier CSS custom properties system:**
```css
/* 1. Global tokens — the complete palette (never used directly in components) */
:root {
--blue-600: #2563eb;
--blue-500: #3b82f6;
--red-500: #ef4444;
--green-600: #16a34a;
--gray-50: #f8fafc;
--gray-900: #0f172a;
--space-4: 1rem;
--space-6: 1.5rem;
--radius-md: 0.375rem;
}
/* 2. Semantic tokens — meaningful aliases (components consume these) */
:root {
--color-brand-primary: var(--blue-600);
--color-brand-secondary: var(--blue-500);
--color-surface: var(--gray-50);
--color-on-surface: var(--gray-900);
--color-price: var(--gray-900);
--color-price-sale: var(--red-500);
--color-success: var(--green-600);
}
/* 3. Dark mode overrides */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--color-surface: var(--gray-900);
--color-on-surface: var(--gray-50);
}
}
[data-theme="dark"] {
--color-surface: var(--gray-900);
--color-on-surface: var(--gray-50);
}
/* Components only use semantic tokens */
.btn-primary {
background: var(--color-brand-primary);
border-radius: var(--radius-md);
min-height: 44px;
}
.price--sale { color: var(--color-price-sale); }
```
**Dark mode toggle (stores preference in localStorage):**
```jsx
export function ThemeToggle() {
const [theme, setTheme] = useState(() => localStorage.getItem('theme') ?? 'system');
function applyTheme(newTheme) {
setTheme(newTheme);
localStorage.setItem('theme', newTheme);
if (newTheme === 'system') document.documentElement.removeAttribute('data-theme');
else document.documentElement.setAttribute('data-theme', newTheme);
}
return (
<button onClick={() => applyTheme(theme === 'dark' ? 'light' : 'dark')}
aria-label={`Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`}>
{theme === 'dark' ? 'Light mode' : 'Dark mode'}
</button>
);
}
```
**Prevent dark mode flash (apply before render):**
```html
<!-- In <head>, before any stylesheets -->
<script>
(function() {
var theme = localStorage.getItem('theme');
if (theme === 'dark' || (!theme && matchMedia('(prefers-color-scheme: dark)').matches))
document.documentElement.setAttribute('data-theme', 'dark');
})();
</script>
```
**Multi-tenant white-label (inject per-tenant overrides server-side):**
```javascript
// In your server response, inject tenant CSS overrides in <head>
// so they're applied before the page renders (no flash)
const tenantTheme = await getTenantTheme(req.hostname);
const cssOverrides = tenantTheme
? `:root { ${Object.entries(tenantTheme)
.map(([k, v]) => `--${k}: ${sanitizeCssValue(v)};`)
.join(' ')} }`
: '';
// Sanitize to allow only safRelated in storefront-ui
product-comparison
IncludedLet shoppers select multiple products and compare them side-by-side in a table with highlighted differences to help them make the right buying decision
faceted-navigation
IncludedLet shoppers filter products by multiple attributes simultaneously with URL-shareable filter state, instant results, and mobile-friendly controls
mega-menu-builder
IncludedBuild a rich navigation mega menu with product images, category highlights, featured banners, and keyboard-accessible dropdowns for large catalogs
product-page-design
IncludedDesign high-converting product detail pages with image galleries, variant selectors, social proof, and clear calls-to-action that drive add-to-cart
quick-view-modal
IncludedLet shoppers preview product details and add items to cart from the listing page without navigating away, reducing friction in the shopping flow
accessibility-commerce
IncludedMake your store usable by everyone with WCAG 2.1 AA compliance — screen reader support, keyboard navigation, and accessible cart and checkout flows