# Replace InStore POS UI modules Replace a component of the InStore POS with a micro-frontend that you build and host, registered as an external module. ## How POS UI module replacement works The InStore POS is a host application that loads each of its components as a separate micro-frontend using Module Federation. Module Federation calls each loaded micro-frontend a remote. In InStore, you register a replacement as an external module. An external module is a record that tells the POS to load your replacement module in place of a built-in component. You register the external module once for your tenant. Then assign it to a location or to a workstation. When a workstation starts, InStore resolves which external modules apply to it. It returns them with the rest of the workstation configuration. The POS loads your replacement module from the address in the record. Registration and assignment are configuration. The replacement module itself is code that you build, host, and serve. ## Component you can replace The Cart is the only component you can replace. To review the full set of InStore modules and the kind of customization each one supports, see [Use Modules overview](/instore/implement-instore/modules/working-with-instore-modules.md). That page covers styling and parameter customization. These options change how a built-in module looks and behaves. Module replacement substitutes the module itself. An external module record describes where your replacement module lives and how to load it. The record contains the following fields: | Field | Data type | Description | | --- | --- | --- | | `default` | Boolean | Whether the module is the tenant-wide fallback for its type. At most one module per type can be the default. | | `key` | String | Unique identifier for the module within your tenant. Accepts 2 to 256 letters, digits, underscores, and hyphens. | | `module` | String | Path that the replacement module exposes for the component, such as `./CartApp`. | | `scope` | String | Module Federation container name that the replacement module exposes, such as `instoreCart`. | | `type` | String | Component that the replacement module provides. See [Component you can replace](/instore/customization/pos-ui-modules.md#component-you-can-replace) for supported values. | | `url` | String | Address of the `remoteEntry.js` file for the replacement module. Accepts `http` and `https` addresses up to 2048 characters. | The following request body registers a Cart replacement module: ```json title="External module request body" { "key": "external-cart-component", "url": "https://modules.example.com/InStore_Example_Cart/remoteEntry.js", "type": "Cart", "scope": "instoreCart", "module": "./CartApp", "default": true } ``` A replacement module runs inside the POS host and shares the host React instance. It renders within the same providers as a built-in module. Build the replacement module against the Module Federation contract of the component it replaces. Expose the container name and module path that you register. Due to its hosted nature, the InStore POS loads a replacement module only through the Module Federation contract described on this page. A replacement module that does not expose the registered container name and module path fails to load. The component is then unavailable at every workstation the module is assigned to. Assignments follow three rules: - Each location and each workstation accepts at most one external module per type. To swap an assigned module, remove the existing assignment first. - An external module that is still assigned to a location or a workstation can't be deleted. Remove every assignment first. - At most one external module per type can be the tenant default. ## The InStore State module The POS keeps its shared state and services in the InStore State module, published as `instoreState` and consumed through Module Federation. That module owns the active Cart, localization, workstation configuration, the API client, and the theme. Every built-in component reads from it rather than holding its own copy. A replacement module works the same way. It declares `instoreState` as a Module Federation remote and reads what it needs from there instead of calling the InStore backend on its own. This keeps a replaced component and the rest of the POS aligned on one Cart, one locale, and one session. For the build setup that every replacement module needs, see [Build a replacement module](/instore/customization/pos-module-development.md). ## Module resolution model InStore consults three tiers to decide which external modules apply to a workstation. It uses the first tier that yields an assignment: 1. Assignments on the workstation. 2. Assignments on the parent location. 3. External modules marked as the tenant default. Tiers apply as a whole rather than merging by type. If a workstation assigns any external module, that assignment set answers in full. The workstation inherits nothing from its location. If no tier yields an external module, the POS loads the module bundled with it. ```mermaid flowchart TD WS{Workstation
assignments?} LOC{Location
assignments?} DEF{Tenant default
modules?} UseWS[Workstation assignment set] UseLoc[Location assignment set] UseDef[Tenant default set] Bundled[Module bundled with the POS] POS[Module loaded at the workstation] WS -->|yes| UseWS WS -->|no| LOC LOC -->|yes| UseLoc LOC -->|no| DEF DEF -->|yes| UseDef DEF -->|no| Bundled UseWS --> POS UseLoc --> POS UseDef --> POS Bundled --> POS classDef src fill:#C2C2FF,stroke:#6359FF,stroke-width:2px,color:#191741; classDef src2 fill:#9FF7EE,stroke:#08A88A,stroke-width:2px,color:#003037; classDef proc fill:#FFE7A8,stroke:#FFC738,stroke-width:2px,color:#191741; classDef out fill:#8F8FFF,stroke:#4E4ED7,stroke-width:2px,color:#191741; classDef fin fill:#F9C9C0,stroke:#FF8A00,stroke-width:2px,color:#191741; class WS,LOC,DEF proc; class UseWS,UseLoc,UseDef src; class Bundled src2; class POS fin; ``` Changes take effect the next time the POS loads at that workstation. ## Relationship to POS theming Theming and module replacement address different needs. A theme restyles the modules that ship with the POS and leaves their behavior in place. A replacement module substitutes the module itself. Its behavior and markup are yours. Because the replacement module renders inside the host providers, it can read the tenant theme. Applying that theme is your responsibility. To change the appearance of the built-in modules instead, see [Customize the InStore POS UI](/instore/customization/pos-overview.md). ## Next steps Use the following resources to continue developing your replacement module: - [Build a replacement module](/instore/customization/pos-module-development.md) to build a replacement module against the InStore State module and register it. - [Implement the Cart module](/instore/customization/pos-cart-module.md) to read Cart state and render a replacement Cart. - [Run POS API requests](/instore/customization/pos-api-access.md) to set the API host, Project, and tenant, get an access token, and send requests to InStore POS APIs. - [Use Modules overview](/instore/implement-instore/modules/working-with-instore-modules.md) to review the InStore modules and the customization each one supports. - [Customize the InStore POS UI](/instore/customization/pos-overview.md) to learn how tenant theming applies across the POS. - [Customize styles and behavior](/instore/customization/pos-theming.md) to change palette tokens, MUI component overrides, and responsive layout settings. ## Related pages - [Area overview page with navigation](/instore.md) - [Search documentation and API specs](/search.md)