Build Once, Launch Many
Every artist needs digital presence that feels like nobody else.
In parallel, fans expect their e-commerce storefronts to be familiar, as measured in Familiarity Sells.
These two requirements naturally pull in opposing directions. Structured theming aligns them: a multi-layered schema of configuration driving controlled flexibility.
Themes + Component Library
= A Scalable Platform
Component libraries are crucial for solid platform architecture - Sanity's deep-dive covers the ground - but fans see unique experiences, not the platform. Theming is the critical lever through which brand identity is surfaced.
The shared component library has theming levers throughout all its layers, from <html> down to leaf <Components>. Theme configuration gives each artist a distinct look and feel without rebuilding the underlying behaviour.
Themes can be modelled as single, structured JSON documents, that describe how a site looks within the predefined parameters.
Switching between the theme options below previews the impact:
{
"schemaVersion": 1,
"meta": {
"id": "allgold",
"name": "All Gold",
"artist": "All Gold"
},
"tokens": {
"palette": {
"background": {
"background": "#fbfbf9",
"foreground": "#20210d"
},
"card": {
"background": "#ffffff",
"foreground": "#20210d"
},
"popover": {
"background": "#ffffff",
"foreground": "#20210d"
},
"primary": {
"background": "#20210d",
"foreground": "#fbfbf9"
},
"secondary": {
"background": "#eceae1",
"foreground": "#6b6b5e"
},
"muted": {
"background": "#eceae1",
"foreground": "#6b6b5e"
},
"accent": {
"background": "#20210d",
"foreground": "#fbfbf9"
},
"destructive": {
"background": "#20210d",
"foreground": "#fbfbf9"
},
"warning": {
"background": "#eceae1",
"foreground": "#6b6b5e"
},
"error": {
"background": "#20210d",
"foreground": "#fbfbf9"
},
"outline": {
"background": "transparent",
"foreground": "#20210d"
},
"border": "#e4e3dc",
"input": "#ffffff",
"ring": "#20210d"
},
"typography": {
"fontHeading": "inherit",
"fontBody": "inherit",
"fontAccent": "inherit",
"fontMono": "JetBrains Mono",
"leadingHeading": "1.2",
"leadingBody": "1.5",
"leadingTertiary": "1.4",
"trackingTight": "-0.01em",
"trackingNormal": "0rem",
"trackingWide": "0.1em",
"trackingWidest": "0.16em",
"trackingHeading": "-0.02em"
},
"spacing": "0.75rem",
"radius": {
"base": "0.5rem",
"default": "0.5rem"
},
"shadows": {
"x": "0px",
"y": "2px",
"blur": "8px",
"spread": "0px",
"opacity": "0.08",
"color": "#20210d",
"presets": [
"sm",
"md",
"lg"
]
},
"motion": {
"loaderTransitionDuration": 200,
"loaderTransitionEasing": "0.19, 1, 0.22, 1"
},
"layout": {
"gridCols": [
2,
3,
4
],
"gridGap": "0.75rem"
},
"modes": {
"boxed": false,
"toggleShape": "square"
},
"borders": {
"svgStrokeWidth": "1.5"
}
},
"shell": {
"htmlBackgroundColor": "#fbfbf9",
"bodyBackgroundImage": null,
"bodyBackgroundSize": "auto",
"bodyBackgroundPosition": "center",
"bodyBackgroundRepeat": "no-repeat",
"bodyBackgroundAttachment": "fixed",
"bodyBackgroundOpacity": "1",
"fontStyle": "normal",
"textTransform": "uppercase"
},
"primitives": {
"button": {
"typography": {
"transform": "uppercase",
"tracking": "0.08em"
},
"radius": "0.5rem",
"variants": {
"default": {
"background": "#20210d",
"foreground": "#fbfbf9"
},
"outline": {
"background": "transparent",
"foreground": "#20210d"
}
}
},
"badge": {
"typography": {
"transform": "uppercase"
},
"radius": "0.5rem",
"size": "sm",
"variants": {
"default": {
"background": "#eceae1",
"foreground": "#6b6b5e"
}
}
},
"select": {
"radius": "0.5rem",
"variants": {
"default": {
"background": "#ffffff",
"foreground": "#20210d"
}
}
},
"toggle": {
"radius": "0.5rem",
"variants": {
"selected": {
"background": "#20210d",
"foreground": "#fbfbf9"
}
}
},
"toggleGroupItem": {
"radius": "0.5rem"
},
"alert": {
"radius": "0.5rem",
"variants": {
"default": {
"background": "transparent",
"foreground": "#20210d"
}
}
},
"checkbox": {
"radius": "0.5rem",
"checked": "#20210d"
},
"breadcrumb": {
"typography": {
"transform": "uppercase"
},
"color": "#6b6b5e"
},
"heading": {
"typography": {
"weight": "800",
"transform": "none"
}
},
"label": {
"typography": {
"transform": "uppercase",
"tracking": "0.08em"
}
},
"nav": {
"typography": {
"transform": "uppercase"
}
}
},
"components": {
"header": {
"backgroundColor": "#fbfbf9",
"foregroundColor": "#20210d",
"sticky": true,
"rounded": false
},
"footer": {
"backgroundColor": "#fbfbf9",
"foregroundColor": "#20210d",
"secondaryForeground": "#6b6b5e"
},
"footerNav": {
"collapsible": true
},
"chatWidget": {
"brandColor": "#20210d"
},
"productDetails": {
"galleryLayout": "stacked",
"buyPanelSticky": true
},
"productListing": {
"titleVariant": "heading",
"backgroundColor": "#fbfbf9",
"visualNavigation": false
},
"productCard": {
"textAlignment": "left",
"pricePosition": "below",
"aspect": "1 / 1"
},
"card": {
"backgroundColor": "#ffffff",
"radius": "0.5rem"
},
"sectionHeading": {
"align": "left",
"eyebrow": true
},
"accordion": {
"radius": "0.5rem",
"dividers": true
},
"sortFilter": {
"layout": "inline",
"radius": "0.5rem"
},
"carousel": {
"controls": "arrows",
"peek": true
},
"quantitySelector": {
"radius": "0.5rem",
"size": "md"
},
"filters": {
"layout": "drawer",
"showCounts": true
},
"marketCurrencyPicker": {
"variant": "select"
},
"newsletter": {
"layout": "inline",
"headingFont": "inherit",
"fieldDensity": "comfortable"
},
"cart": {
"showBreadcrumbs": false,
"backgroundColor": "#fbfbf9",
"titleFontSize": "lg"
},
"promoGroup": {
"textPosition": "bottom",
"titleFontSize": "lg"
},
"softRedirect": {
"variant": "banner"
}
}
}Theme Builder
The above demo is purely illustrative. In production, the concept extends to a standalone Theme Builder application. It lives in parallel but is isolated to the content CMS or product configuration. Themes can be crafted in a stable environment - before a single product exists, before brand photography is signed off, before anyone writes content copy.
The direction owes a lot to shadcn/ui and tweakcn's theme editors, which showcase a preview interface rather than an abstracted palette.
Theme Ladder
Four levels of configuration operating at different layers of the UI stack:
Tokens are the foundational design directions: palette, typography, radius, spacing, shadows, motion, breakpoints, global defaults.
- Theme Builder: Tokens
Primitives are the smallest reusable building blocks of the UI: buttons, badges, selects, toggles, alerts, breadcrumbs, headings, labels, navigation. The Builder renders every primitive in every possible state - eg default, hover, focus, disabled, unavailable. Because these are the same components as the live sites, there is zero drift between design and engineering.
- Primitives
Components are the page sections a store is assembled from: header and footer, heroes, promo groups, product cards, listing and filter controls, product detail, cart, newsletter, discography, tour dates, video carousels, news.
- Components
Templates are the routes themselves: home, listing, product, search, discography, release, news. This is the check that matters most, because every level below can be right on its own and still combine into a page that is not. Each template renders the production route, so what is reviewed is what the store will serve. Whole pages, before launch, instead of a late and expensive round of visual fixes.
- Templates: home
- Templates: search
- Templates: discography
Custom Experiences are totally unique to the artist, and don't belong in a shared library for others. For example, a snowy background, microsite for a campaign, secret easter eggs. These are modelled as structured exceptions within the code, as component tree leaf nodes. Still driven by theming configuration and simple to elevate into the shared library if appropriate.
One Request, One Document
None of this reaches the browser as JSON configuration. A fan asks for a page, and the theme is transformed into the delivered experience.
When the browser requests a page on an artist's site, the server fetches the assigned Theme JSON during the handler alongside the page content. From there, it fans out to separate transformers:
-
CSS variables are set shared for tokens and settings like colour, spacing, radius, shadow. Heavy usage of Tailwind Theme.
Tokens Primitives -
@font-facerules for typography sets.
Tokens -
React context values, for opt-in usage within components.
Components Templates
All three feed into <html> that's returned to the fan. The theme is set in the first byte.
Build Once, Launch Many
If you run more than one storefront and want the next launch to be configuration, not code, speak to us at [email protected].