Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.frontic.com/llms.txt

Use this file to discover all available pages before exploring further.

Shopping experiences rarely live in one market, one language, or one audience. You sell into different regions, in different currencies, in different languages — and you probably want the same platform to serve B2B and B2C, retail and wholesale, brand A and brand B, without maintaining a parallel project for each. Frontic is built for that from day one. This page explains how scopes, regions, locales, currencies, and domains compose into a multi-market stack — and how you write your blocks and storages once while the stack delivers the right variant to each caller.

The four axes

Scope

Who is asking. B2B, B2C, wholesale, different brands, different loyalty tiers. Scopes let you ship variations of the same content to different audiences without branching your data model.

Region

Where they are. A region is a geographic market — United States, Germany, Europe, DACH. Each region carries its own currency and its own set of supported locales.

Locale

What language they speak. Locales are language codes (en, de, fr-CA). Translatable fields in your storages return the variant matching the resolved locale.

Domain

How they arrived. Domains map URLs (e.g. www.demo-shop.com/de, b2b.demo-shop.com/en) to a specific scope + region + locale combination. The mapping is how request context gets resolved automatically for public traffic.
These four axes work together. A caller arrives at a domain → the domain determines their scope, region, and locale → that combination shapes every block, listing, and page response they get back. You configure the axes once in Project Settings and never think about them again.

Configure your axes

The big idea: one project serves every market. You don’t spin up a separate Frontic project per country, per language, or per brand. Pair the project with the codebase that renders it — generated client, release history, and deploy pipeline all line up against that one repo — and compose markets inside the project via regions, locales, currencies, and scopes. Parallel projects for parallel markets fight the grain.

Define regions

Add the regions you serve — “US”, “Germany”, “Europe (ex-DE)”, “UK”. Each region is a geographic unit with:
  • a default locale
  • a supported locale list
  • a currency the stack uses for pricing responses in that region

Define locales

Add the languages you support — en-US, en-GB, de-DE, fr-CA. Locales are global to the project; regions reference them. You can have locales that aren’t available in every region (e.g. fr is available in Europe and Canada but not in the US).

Define scopes

Most projects start with a single default scope — public. Add scopes if you need audience variants: b2b, wholesale, staff, loyalty-gold. Scoped fields in your storages (see below) are only returned when the caller’s scope matches.

Map domains

Configure the domains where your experience lives and map each one to a scope/region/locale combination. This is how public traffic gets its request context without any client-side logic.
See Project Settings for the full configuration reference.

Storage field flags

On Data Storage fields, three flags let you control how a field behaves across the four axes:

Translatable

The field holds a different value per locale. A translatable name field on a product storage has a German variant, an English variant, a French variant, etc. The stack serves the right one based on the caller’s resolved locale.

Scoped

The field is only available in specific scopes. A scoped wholesalePrice field exists only in the wholesale scope. Callers in the public scope never see it, and listings can’t filter on it from the public scope.

Array

The field holds multiple values. Tag lists, multi-image galleries, multi-category assignments. Combines with Translatable and Scoped — you can have a translatable array field of tags that differ per language and per scope.
Plus the product-specific Shared Across Variants flag (see Product Models) which controls whether a field lives at the product or variant level. You mark a field once with the combination that fits — Translatable: true, Scoped: false, Shared Across Variants: true for a product description that’s the same for every variant but different per language — and the stack takes care of the rest.

Example: a product across markets

Here’s how a single Products Data Storage serves a multi-market catalogue:
FieldFlagsHow it behaves
nameTranslatable, Shared across variantsSame across variants of one product, different per locale
descriptionTranslatable, Shared across variantsAs above
price(variant-level, built-in)Same record across scopes/locales, but auto-returned in the caller’s region currency
wholesalePriceScoped to b2bReturned only to B2B callers; invisible to public scope
swatchImage(per-variant)Variant-specific media, returned based on which variant is resolved
seoTranslatable, Shared across variantsSEO composite — title, description, keywords resolve per locale
All of the logic that makes this work is in the storage schema. Your blocks and listings don’t care — they reference the fields they need, and the stack returns the right values for the caller.

Shared blocks and listings

Because Detail Blocks, Search Listings, and Page URLs all read from a context-aware Data Storage, you don’t need market-specific API surfaces. A single ProductHero block serves every market. A single ProductList listing serves every market. A single /products/:slug page resolves to different records per domain — but you wrote the page once. That’s the payoff of commerce-native infrastructure: the hard problems of multi-market commerce are solved in the stack, not in your code. You spend your time on the experience, not on plumbing locale-aware data fetching into every component.

Common patterns

One region, multiple locales. Mark all user-facing text fields Translatable. The same product records serve every language because the stack substitutes the localized field values at response time.
Two scopes: public and b2b. B2B-only fields (wholesale pricing, bulk discounts, tax-exempt flags) are Scoped to b2b. B2B domains map callers into the b2b scope. Public domains stay in public. One set of blocks, one set of listings, two fully-different experiences.
One scope per brand. Each brand gets its own domain(s) mapping into its scope. Shared primitives (product categories, shared content) stay unscoped and are reused; brand-specific content lives in scoped fields or scoped Data Storages.
Add the locale to the project, add it to the regions it’s available in, let translators fill in the translatable fields over time. Blocks and listings keep working — callers in other locales aren’t affected — and the moment a translation lands, it flows through.

Product Models

How products and variants compose with the scope/region/locale axes.

URLs, Redirects & SEO

How domains translate into actual URLs — and how URL history survives every release.

Request Context

The full picture of how scope, region, and locale get resolved per request.