Multi-Store (parent / child tenants)
When a brand runs multiple Shopify storefronts, regional sites, B2B / B2C splits, market-specific microsites, they don't need a separate copy of the catalog per store. Multi-Store lets one parent tenant share its proprietary catalog with N child tenants, each running an independent storefront with its own pricing, its own stock, and its own subset of the catalog activated.
The problem it solves
A brand like "Northforge" might run:
northforge.com, the main store with ~65,000 SKUs, full catalognorthforge-europe.com, EU-focused subset, EUR pricingb2b.northforge-europe.com, wholesale prices, same SKUs as abovenorthforge-canada.com, CAD pricing, North-American shipping logic
All four are independent Shopify stores. Each carries a subset of the main catalog. Each has different pricing. Each has its own stock. Without Multi-Store, the brand has to maintain four copies of the catalog and synchronise updates by hand, every new product, every description tweak, every fitment correction has to be replicated four times.
Multi-Store flips it: the catalog lives once on the parent tenant. The other three stores are child tenants that read the parent's data live, activating the items they want to carry and setting their own pricing and stock per item. A description fix on the parent flows to every child instantly. A new SKU added on the parent shows up in every child's activation list automatically.
How it maps to the data model
- Parent tenant
- A regular PowersportOS tenant that has TenantParts (proprietary SKUs the brand maintains) + central-catalog brand subscriptions. Nothing special about it from a data perspective, it's just a normal tenant that happens to have children attached.
- Child tenant
- Another tenant with
parentTenantIdset to the parent's id. The child still owns its own dealers, its own Shopify install, its own users, its own optional own-TenantParts. It just also has access to the parent's catalog as a third source. - Activation row
- Each parent-sourced SKU the child carries is a
TenantParentItemrow holding the child'sactiveflag plus optionalpriceandstockoverrides. Canonical part data (name, brand, description, fitments, images) lives on the parent's TenantPart and reads live.
What the child sees
From a child tenant's perspective, their storefront pulls from three sources, merged transparently:
- Central catalog, brands the child has subscribed to directly (Umbr-curated SKUs).
- Parent's proprietary catalog, the parent's TenantParts the child has activated via
TenantParentItem. - Own proprietary catalog, the child's own TenantParts, if any (typically not used for child stores in a Multi-Store group, since everything proprietary lives on the parent).
The /api/t/* storefront endpoints merge all three on the fly. End customers don't see the distinction; for them it's one catalog.
What's intentionally constrained in v1
- Single-level hierarchy. A tenant is either a parent or a child, never both. No grandparents, no chains.
- One parent per child. A child reads from exactly one parent. Most "shared catalog" use cases reduce cleanly to this, branching parents come up rarely enough to defer.
- Read-only flow downward. Children can't push fitments or content back to the parent. The parent is the source of truth.
- Parent's
TenantVehiclesaren't surfaced. v1 only exposes parent's TenantParts that fit central Vehicles. Custom-defined vehicle entries on the parent stay parent-local for now. Covers the 95% case (custom kits fitting OEM bikes); we'll lift it when a customer needs it. - Stock is per-child. Each child has its own stock count for each activated part, they don't share stock with the parent or with siblings. Pushing stock via the
/api/integrations/stock-feedendpoint with a child's API key only updates that child's activation rows.
Onboarding flow
The parent/child relationship is set up by the PowersportOS team during onboarding, it's not self-service from the portal. The flow:
- You contract with us for Multi-Store. We set up both the parent and the child tenants in our admin.
- Each tenant gets its own API key, own Shopify install link, own portal login. Independent operations.
- On the admin side we set
parentTenantIdon the child(ren), attaching them to the parent. - You log into the child portal. A new Group section appears in the sidebar listing the parent's catalog. Activate the items you want; set price and stock per item.
- End-customers visiting the child's storefront see parent-sourced parts merged into the YMM and product-page flows automatically, with your store-specific pricing.
What stays per-tenant (i.e. doesn't share with siblings)
- Pricing and stock per activated item, child-specific.
- Dealer / store-locator data, child has its own dealers.
- Shopify install + theme settings, each child runs its own Shopify store.
- SKU aliases, each child manages its own alias mappings.
- Brand subscriptions to the central catalog, each child subscribes independently (parent's subscriptions don't propagate).
- Users, each child has its own portal users.
What's shared (i.e. flows from parent to children)
- Catalog content on the parent's TenantParts, name, brand, description, images, fitments, OEM cross-references, dimensions, EAN, country of origin.
- New SKUs added to the parent, they appear in every child's activation list automatically.
Pricing variations across children
Per-store price overrides are exactly the use case Multi-Store is designed for. The most common patterns:
- Currency-converted
- Parent in EUR, children in EUR / GBP / CAD / USD with each child carrying converted prices for their market.
- Wholesale vs retail
- Parent + B2C children carry full retail prices; B2B child carries the same SKUs at trade prices. Same catalog content, different price column.
- Market-specific premium
- Children in higher-cost markets (logistics, duties, taxes) carry a markup over parent's pricing for the same parts.
None of these patterns require parent-side awareness, each child sets its own prices independently in the Group page.
Why this isn't a marketplace pattern
Multi-Store looks superficially like a marketplace (one platform serving multiple storefronts with overlapping inventory) but it's deliberately not. The hierarchy is single-brand: all the children belong to the same legal entity (or group), the parent owns the catalog content, and there's no end-customer-facing "PowersportOS marketplace" surface. Each child storefront is a fully independent Shopify store with its own domain, branding, and customer relationship. The platform just removes the catalog-duplication tax that running multiple stores would otherwise impose.