Multi-Store Architecture
A single Maho Storefront Worker deployment can serve multiple stores, each with its own theme, component configuration, and isolated catalog data.
| Fashion Store | Tech Store |
|---|---|
![]() | ![]() |
Store Resolution
Configuration
stores.json
Maps store codes to theme and page config files:
{
"stores": {
"en": {
"theme": "maho",
"pageConfig": "page.json"
},
"sv_2": {
"theme": "tech",
"pageConfig": "page-tech.json"
},
"store_view_3": {
"theme": "brew-beyond",
"pageConfig": "page-brew-beyond.json"
}
},
"defaultTheme": "maho",
"defaultPageConfig": "page.json"
}Store Registry
The store registry maps hostnames to store codes. It can be stored in KV (key: _stores) or configured as a Wrangler environment variable (DEMO_STORES):
{
"demo.mageaustralia.com.au": "en",
"demo2.mageaustralia.com.au": "sv_2",
"cafe.mageaustralia.com.au": "store_view_3"
}Data Isolation
Each store's data is isolated in KV via key prefixes:
| Store | Key Example | Content |
|---|---|---|
en | en:product:tori-tank | English store product |
sv_2 | sv_2:product:tori-tank | Tech store product |
en | en:config | English store config |
sv_2 | sv_2:config | Tech store config |
This ensures:
- Products can have different prices per store
- Categories can be structured differently
- CMS content is store-specific
- Config (currency, locale) varies per store
Render Context
Before rendering any page, the store context is set:
// In route handler
const storeCode = getCurrentStoreCode(hostname, storeRegistry);
setRenderStore(storeCode);
// All components now use this store's config
const variant = getVariant('product', 'gallery'); // Uses store's page configThe render context is a module-level variable — set once per request, read by all components during synchronous SSR.
Theme Switching
Each store renders with its theme's CSS custom properties:
<!-- Store "sv_2" renders with tech theme -->
<html data-theme="tech">The [data-theme="tech"] selector activates the tech theme's CSS custom properties, overriding the default :root values. All DaisyUI components and utility classes automatically use the store's colors, fonts, and spacing.
Adding a New Store
- Add the store code and configuration to
stores.json - Create a theme file (
theme-{name}.json) if needed - Create a page config (
page-{name}.json) if needed - Add hostname → store code mapping to the store registry
- Sync data for the new store:
POST /sync(will fetch data for all registered stores) - Rebuild CSS:
bun run build:css(generates new theme CSS) - Deploy:
bun run deploy
Source: src/index.tsx, src/page-config.ts, stores.json

