Micro Experiences Developer Guide
Understanding MX Architecture

Your engineering team needs to be familiar with Micro Experiences architecture in order to work with multiple experiences comfortably. It’s important to know key concepts like how a public request gets routed, or how developer tools and PageBuilder configuration is nested under each experience.
If you haven’t read How does Micro Experiences work? we suggest starting from this document.
Understanding the New MX Router and Its Relationship to Resolvers
The MX router is a critical component that directs traffic to the appropriate Micro Experience based on the requested URL. Resolvers in PageBuilder still play a key role in determining how content is fetched and displayed. When working with MX, you’ll need to configure each micro experience, and know all other requests that don’t match with an experience’s site and path prefix mapping will be routed to your default experience. New MX router acts as a parent routing system between experiences. It’s not the only place you will need to consider your site URLs. Once a site + path matches with an experience, request follows that experience’s Resolver configurations.
Here is a diagram shows how MX Router and a specific MXs’ resolver works together to resolve a URL the reader clicks.

The reason we kept resolver configurations unchanged because resolvers depends on the content of your bundle, like your content sources gets called to resolve a dynamic URL. For this reason there are two distinct routing systems you need to interact with, when using Micro Experiences. This gets much simpler if you are mapping experiences to domains.
How to Work on Multiple Codebases
PageBuilder and Micro Experiences is agnostic to having your bundles managed in separate repositories or single repository. To each deployer, it needs a bundle zip file for that experience whether it is coming from separate repositories, or same repository, or even if it’s exact same bundle.
Simplest way to think about this is obviously, separate repositories, separate bundle code that you can simply zip. Setting each repository’s CI/CD pipelines and seeing pipeline activities separately will be very simple.
Managing multiple bundles for separate micro experiences in a centralized way, or reducing code duplication to be minimal can get challenging. There are a few different common engineering practices to do this:
-
NPM Packages: Separate codebases, but maintain common/shared parts to modularize them like npm packages. This is a great option and have benefits like better testability, easier to maintain individual parts. But if it gets too fragmented, it can get challenging to track of individual package’s dependencies and upgrades in the future (i.e: node.js upgrades to be done for each package).
-
Git Submodules: Another option is to host your common parts of your experiences in a separate repository, let’s call this core-experience, or shared-experience. You can include this as a module in your experiences and import the parts you commonly use in that specific experience. You may not need to import everything, just the parts you use in that experience. Learn more about git submodules.
-
Monorepo: Another common practice used by both large enterprises, and smaller team managing many mini projects under single repository. There are many monorepo tooling exists that provides tool chain for managing both smaller packages as well as larger projects under same folder structure. You can learn more about monorepo and tooling in https://monorepo.tools/. If you’re interested in mono repo approach, we covered our best practices in Adopting monorepo with Micro Experiences
You can choose your own unique approach based on your teams preference.
Local Development Changes
Local development experience is not impacted by Micro Experience. Your team can continue using the CLI to run your bundle locally without any change. You may notice newer version of docker containers will be downloaded that provides support for MX compatibility if you are not pinning versions (i.e: engine, themes).
When working on multiple bundles, you need to run each bundle one at a time. You can not run multiple bundles at the same time.
Deployment Process
When working with multiple PageBuilder instances, you will have separate Deployers to work with. Both Deployer UI and API works with a top-level mxId
context. This context is being set in the UI when you select the PageBuilder from Arc Home. Rest of the Deployer UI is identical to what you see today. Each Deployer action (upload, deploy, promote, terminate) and the deployment data (history) you see will be using that context under behind the scenes.
When working with Deployer API, you will need to provide mxId
in each API call. It’s a new parameter can be provided in query string or request bodies. A sample Deployer API call to promote a bundle, with mxId
provided:
Get list of bundles:
Before (without MX): | After (with MX - for a specific MX’s bundles): |
/deployments/fusion/bundles | /deployments/fusion/bundles?mxId=abcd1234 |
Promote a deployment live (deployment id: 15):
Before (without MX): | After (with MX - for a specific MX’s bundles): |
/fusion/deployments/15/promote | /fusion/deployments/15/promote?mxId=abcd1234 |
When not provided, we will treat this as “default” experience request and process your API request within the default experience’s deployer. This makes Micro Experiences backwards compatible and non-breaking. Your existing integrations and CI/CD scripts will continue to work without any change for your default experiences.
See PageBuilder Deployer API for reference.
Changes in Resource URLs
As far as the changes required for your codebase, this is the only update you need to make to your codebase to make it become MX-compatible.
Customers who want to refer to static resources from components, use the deployment()
function to wrap static asset references, like deployment('/pf/resources/my-icon.svg')
This method adds the deployment parameter to the resource URLs (i.e: /pf/resources/my-icon.svg?d=203
) in the final bundle and HTML so that each deployment refers to its static resources (example scenario: your readers gets the update to your logo when you deploy a new bundle, even if it was previously cached on readers browser).
Now instead of deployment()
method, you need to use the new pageBuilderURL()
function which is identical how it works, but now it also adds the mxId
to resource paths, so each bundle resources can be correctly served (i.e: /pf/resources/my-icon.svg?mxId=2e76c538&d=56
).
A common use case is in your output types:
export default ({ contextPath, deployment }) => ( <html> <head> ... <link rel='icon' type='image/x-icon' href={pageBuilderURL(`${contextPath}/resources/favicon.ico`)} /> <link rel='stylesheet' type='text/css' href={pageBuilderURL(`${contextPath}/resources/styles/main.css`)} /> </head> ... </html>)
Page Performance Impact
Your readers page performance may be impacted by Micro Experience. Most practical scenarios with splitting a large experience to multiple Micro Experiences results positive reader impact, where client-side bundle for each Micro Experience gets smaller.
But in some cases, all resources your reader downloads when browsing from one page to another that are powered by separate Micro Experiences. Even though you have identical features included in your bundles, your client-side bundle will still be unique to each Micro Experience. Similarly, other static assets like react.js, or icons that are included in the bundle will get different deployment identifiers which means your readers browser will download these assets separately. Usually, once your reader opens the first page in your site, most (if not all) static assets gets cached in the browser and it does not get re-downloaded when your reader browses different pages. But with Micro Experience, browser will download duplicate content bundled in different js and css files.
While this sounds like a cache anomaly, in total download size your reader may experience faster page loads in individual pages depending on how many Micro Experiences you split your current bundle to.
Imagine this scenario, a user clicks to a link and reads an article, then clicks to your sports section front page.
Let’s compare how PageBuilder related resources gets downloaded, cached and re-used as the reader navigates between these two pages.
Scenario 1: Single PageBuilder (Current)
- User visits
/news/heat-record-in-houstin
- Browser downloads assets:
/pf/dist/components/combinations/default.css?d=497
51kb/pf/dist/engine/react.js?d=497
95kb/pf/dist/components/combinations/default.js?d=497
508kb/pf/resources/images/logo.svg?d=497
15kb/pf/resources/images/favicon.ico?d=497
2kb/pf/resources/images/footer-bg.png?d=497
30kb/pf/resources/fonts/fonticons.ttf?d=497
48kb
- Browser downloads assets:
- User clicks and visits
/sports
- Browser uses cached assets. No extra download related with the PageBuilder JS/CSS.
Total Download Size for Two Pages: 749kb
Scenario 2: Multiple PageBuilders (Micro Experience)
- User visits
/news/heat-record-in-houstin
- This page gets rendered by “News” Experience.
- Browser downloads assets:
/pf/dist/components/combinations/default.css?d=133&mxId=80f4a77c
34kb/pf/dist/engine/react.js?d=133&mxId=80f4a77c
95kb/pf/dist/components/combinations/default.js?d=133&mxId=80f4a77c
260kb/pf/resources/images/logo.svg?d=133&mxId=80f4a77c
15kb/pf/resources/images/favicon.ico?d=133&mxId=80f4a77c
2kb/pf/resources/images/footer-bg.png?d=133&mxId=80f4a77c
30kb/pf/resources/fonts/fonticons.ttf?d=133&mxId=80f4a77c
48kb
- Total Download Size for this page: 484kb
- User clicks and visits
/sports
- This page gets rendered by “Sports” Experience.
- Browser downloads assets:
/pf/dist/components/combinations/default.css?d=75&mxId=4bf008c1
12kb/pf/dist/engine/react.js?d=75&mxId=4bf008c1
95kb/pf/dist/components/combinations/default.js?d=75&mxId=4bf008c1
127kb/pf/resources/images/logo.svg?d=75&mxId=4bf008c1
15kb/pf/resources/images/favicon.ico?d=75&mxId=4bf008c1
2kb/pf/resources/images/footer-bg.png?d=133&mxId=80f4a77c
30kb/pf/resources/fonts/fonticons.ttf?d=75&mxId=4bf008c1
48kb
- Total Download Size for this page: 329kb
Total Download Size for Two Pages: 813kb
In this example, the biggest portion of your client-side downloaded assets is the combined client-side bundle (default.js) which was around 500kb in single PageBuilder model. When you use and split your experience to multiple Micro Experiences, that single client-side bundle, gets chunked to smaller bundles.
While each MX’s client-side bundle sizes goes down, there is a caveat to this, where both MXes client-side bundles (default.js), will contain same libraries you used in all of your bundles (i.e: lodash, moment.js). Also your static assets, (like your logo, favicon, fonts, static images…) that you use in both experiences will have unique deployment and mxId in their URLs where your browser will treat them as separate files even though they are identical. Even though these files are generally small in size, your reader will need to re-download these for each MX, therefore their total download size for two pages can be larger than a single-bundle approach.
User may not browse parts of your experience that could be split to other experiences, like subs which can improve everyday users experience. In this example their total download size gets smaller for this particular user. From the example above, if a reader only reads 2 sports article and never browse anything else, their total download size will be 329kb compared to single-experience total download size 749kb.
This is also same for your crawlers. When a crawler scans your page, it downloads the page as if it never seen your site. Generally crawlers don’t cache your assets between pages, and they score your pages performance based on no-cache scenario where the total download size per each page will taken account. When you split unique and heavy parts of your current bundle into separate MXes and start optimizing each MXes bundle size, your average download size for each page will go down, therefore they may render faster (because less javascript to load into runtime, and faster downloads because smaller bundle sizes), that may result increased performance on crawlers eyes.
How does images served from photo center impacted by MX?
Your photo content, including resizer implementation works across multiple Micro Experiences. Arc Blocks using resizer also works from multiple experiences.
Subscriptions / Identity
Subscriptions works across multiple Micro Experiences including Arc Identity Blocks from multiple micro Experiences.
Keep in mind that the same identity blocks needs to be configured identically across MX. When making change on the configuration of an identity block, you need to sync/copy the same configuration to all bundles using the Arc Identity blocks in multiple experiences, to ensure smooth UX between pages when your readers browse your site that are powered by different Micro Experiences.
Audience Targeting
Audience targeting is only available on the default MX. This means that you can apply audience targeting strategies solely within your primary/default Micro Experience instance.
Bandito
Bandito, Arc XP’s A/B testing tool, is currently limited to the default MX. You can run experiments and tests only within your primary/default Micro Experience instance.
Clavis
Clavis, Arc XP’s content intelligence tool, is implemented and configured fully on client-side, therefore you can use same Clavis implementation in multiple MX and they will work consistently throughout your experiences.
PB Data Sync API
PB Data Copy is currently only supports the default MX instance. It is not supported on secondary Experiences yet and does not support copying data across different MXs. See PageBuilder Editor Data Sync API.
Alternatively, you can use Export and Import of individual pages and templates between experiences for small amount of pages and templates.
Secondary Orgs
Micro Experiences offers very similar functionality to secondary orgs and it can replace most secondary org use cases. Customers can migrate their current secondary org configurations into a new MX under their primary org. There are a few key areas we want to highlight:
-
PageBuilder data needs to be copied from secondary org production to primary org production under a new MX. This process is a ticketed, manual process that you can request to your TAM after getting new MX provisioned.
-
Your bundle code that runs in your secondary org can be deployed without any change into the new MX. You still need to deploy your existing bundle to new MX using Engine 5.1 or newer version in order to get MX working.
-
Since secondary org can only be configured at the site/domain level, the MX strategy for moving secondary org hosted sites to a new MX should be simpler than other MX use cases. Simply configure new MX to handle all traffic under one or more sites.
-
You may be in production, with live traffic on your secondary org. If that’s the case, traffic cutover needs to be planned by Arc XP Delivery team and you need to treat this similar to a site launch that needs to be carefully planned.
Migration
See Planning your Micro Experience Migration for more detailed guide about migration strategy.
See Developer FAQs in Micro Experiences FAQs