storefront-theming
Build a themeable storefront with design tokens and CSS custom properties that supports white-labeling, multi-brand variants, and dark mode
Best use case
storefront-theming is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Build a themeable storefront with design tokens and CSS custom properties that supports white-labeling, multi-brand variants, and dark mode
Teams using storefront-theming should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/storefront-theming/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How storefront-theming Compares
| Feature / Agent | storefront-theming | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Build a themeable storefront with design tokens and CSS custom properties that supports white-labeling, multi-brand variants, and dark mode
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# 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 safe CSS value patterns
function sanitizeCssValue(value) {
if (/^#[0-9a-fA-F]{3,8}$/.test(value)) return value; // hex color
if (/^\d+(\.\d+)?(px|rem|em|%)$/.test(value)) return value; // length
if (/^[a-zA-Z0-9\s,'"]+$/.test(value)) return value; // font names
return ''; // reject everything else (prevents CSS injection)
}
```
### Step 3: Build a token reference for your team
Regardless of platform, document your tokens so designers and developers stay in sync:
- **Shopify:** The Theme Editor serves as the live token reference — share the Customize URL with your design team
- **WooCommerce:** Document the CSS variable names in a Storybook instance or a simple HTML reference page
- **BigCommerce:** Cornerstone's `config.json` documents available settings; add comments to SCSS files
- **Custom:** Use Style Dictionary to generate a static token documentation page, or document in Storybook
## Best Practices
- **Never hard-code colors in component CSS** — always use semantic tokens; a rebrand that requires global find-replace of `#2563eb` is avoidable
- **Keep semantic token names meaning-based** — `--color-brand-primary` not `--color-blue-600`; the hex value will change but the meaning stays
- **Test dark mode with real devices** — macOS/iOS and Windows have different default dark mode behaviors; test both
- **Validate contrast ratios** — after setting brand colors, verify WCAG contrast ratios (4.5:1 for body text) using WebAIM Contrast Checker
- **Sanitize white-label CSS injections** — only allow hex colors, rem/px lengths, and font names; reject arbitrary strings to prevent CSS injection attacks
## Common Pitfalls
| Problem | Solution |
|---------|----------|
| Dark mode causes flash of unstyled content | Apply `data-theme` attribute synchronously in a `<head>` script before stylesheets load |
| Tenant theme overrides not applied on first render | Inject tenant CSS as inline `<style>` tag server-side; do not apply in `useEffect` |
| Design tokens out of sync between Figma and code | Use Tokens Studio for Figma plugin to export directly to your CSS variable / `theme.json` files |
| White-label CSS enables XSS | Sanitize tenant token values to only allow valid CSS color, length, and font-family patterns |
| Rebranding requires changing many files | If you find yourself replacing colors in multiple component files, you skipped the semantic token layer — refactor to semantic tokens first |
## Related Skills
- @responsive-storefront
- @accessibility-commerce
- @mega-menu-builder
- @product-page-designRelated Skills
responsive-storefront
Build a mobile-first storefront with thumb-friendly navigation, sticky add-to-cart buttons, and touch-optimized components for high mobile conversion
shopify-storefront-api
Build a headless Shopify frontend using the GraphQL Storefront API for product queries, cart management, and checkout with the Buy SDK
pwa-storefront
Turn your store into an installable Progressive Web App with offline product browsing, push notifications, and home screen access for mobile shoppers
jamstack-storefront
Build a blazing-fast storefront with Next.js or Astro that pre-renders product pages as static HTML and fetches live data from commerce APIs
wishlist-save-for-later
Let shoppers save products to a wishlist, share it with friends, and get notified when saved items come back in stock or drop in price
search-autocomplete
Speed up product discovery with instant search suggestions, fuzzy typo matching, and category-aware results powered by Algolia or Elasticsearch
recently-viewed-products
Show shoppers the products they recently browsed using browser storage so they can easily pick up where they left off on your store
quick-view-modal
Let shoppers preview product details and add items to cart from the listing page without navigating away, reducing friction in the shopping flow
product-page-design
Design high-converting product detail pages with image galleries, variant selectors, social proof, and clear calls-to-action that drive add-to-cart
product-comparison
Let shoppers select multiple products and compare them side-by-side in a table with highlighted differences to help them make the right buying decision
mega-menu-builder
Build a rich navigation mega menu with product images, category highlights, featured banners, and keyboard-accessible dropdowns for large catalogs
image-zoom-360
Boost product confidence with high-res image zoom, 360-degree spin views, and inline video so shoppers can examine products closely before buying