> ## 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.

# Multi-Channel & Multi-Region

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

<CardGroup cols={2}>
  <Card title="Scope" icon="users">
    **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.
  </Card>

  <Card title="Region" icon="earth-americas">
    **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.
  </Card>

  <Card title="Locale" icon="language">
    **What language they speak.** Locales are language codes (`en`, `de`,
    `fr-CA`). Translatable fields in your storages return the variant
    matching the resolved locale.
  </Card>

  <Card title="Domain" icon="globe">
    **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.
  </Card>
</CardGroup>

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](/project-settings/general) 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.

<Steps>
  <Step title="Define regions" icon="earth-americas">
    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
  </Step>

  <Step title="Define locales" icon="language">
    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).
  </Step>

  <Step title="Define scopes" icon="users">
    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.
  </Step>

  <Step title="Map domains" icon="globe">
    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.
  </Step>
</Steps>

See [Project Settings](/project-settings/general) for the full configuration reference.

## Storage field flags

On [Data Storage](/data-integration/data-storages) fields, three flags let you control how a field behaves across the four axes:

<CardGroup cols={3}>
  <Card title="Translatable" icon="language">
    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.
  </Card>

  <Card title="Scoped" icon="users">
    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.
  </Card>

  <Card title="Array" icon="list">
    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.
  </Card>
</CardGroup>

Plus the product-specific **Shared Across Variants** flag (see [Product Models](/commerce-concepts/product-models#sharing-fields-across-variants)) 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:

| Field            | Flags                                | How it behaves                                                                       |
| ---------------- | ------------------------------------ | ------------------------------------------------------------------------------------ |
| `name`           | Translatable, Shared across variants | Same across variants of one product, different per locale                            |
| `description`    | Translatable, Shared across variants | As above                                                                             |
| `price`          | (variant-level, built-in)            | Same record across scopes/locales, but auto-returned in the caller's region currency |
| `wholesalePrice` | Scoped to `b2b`                      | Returned only to B2B callers; invisible to `public` scope                            |
| `swatchImage`    | (per-variant)                        | Variant-specific media, returned based on which variant is resolved                  |
| `seo`            | Translatable, Shared across variants | SEO 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](/api-builder/blocks), [Search Listings](/api-builder/listings), and [Page URLs](/api-builder/pages) 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

<AccordionGroup>
  <Accordion title="Same catalogue, different languages">
    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.
  </Accordion>

  <Accordion title="B2B and B2C on the same project">
    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.
  </Accordion>

  <Accordion title="Multiple brands on one platform">
    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.
  </Accordion>

  <Accordion title="Rolling out a new language">
    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.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={3}>
  <Card title="Product Models" icon="boxes-stacked" href="/commerce-concepts/product-models">
    How products and variants compose with the scope/region/locale axes.
  </Card>

  <Card title="URLs, Redirects & SEO" icon="link" href="/commerce-concepts/urls-seo">
    How domains translate into actual URLs — and how URL history survives
    every release.
  </Card>

  <Card title="Request Context" icon="compass" href="/api-builder/overview#request-context">
    The full picture of how scope, region, and locale get resolved per
    request.
  </Card>
</CardGroup>
