Architecture

A framework-agnostic core runs the Experience Transition Protocol. Adapters connect it to React and Next.js. The application sends one request and renders one snapshot.

Layers

Each layer only talks to the one below it. Select a layer to see what it is responsible for.

Experience Engine core

Framework-agnostic. The inspected core source has no direct dependency on browser globals, which is why the same code resolves an experience inside a Next.js Server Component.

new ExperienceEngine({ cultures, themes, motions, initial })

The eight stages of a transition

Every call to setExperience() runs these in order. Select a stage to see what it does and where it lives in the core.

Diff

Compare current and target into a typed delta, per dimension.

In the core
diffSnapshots()
In your last transition
Run a transition in the Studio and this fills in.

How components adapt

A theme can change a component at three depths. The cheapest one that does the job is used.

DepthWhat changesIn Nova CommerceRight now (en-US::light::instant)
TokenThe component stays the same and reads new values.Card radius, colour and shadowradius 12px
VariantThe same component takes a different form.Navigation: labelled rail or icon-onlybase
ReplacementA different component takes its place, and its code is prepared first.Orders: data table or compact listbase

Where the orchestration lives

Without an experience runtime, each of these concerns is something the application coordinates by hand at every place an experience can change. With the engine they sit behind one call.

Orchestrated in the application

  • Culture state
  • Theme state
  • Motion state
  • Resource selector
  • Component branch
  • Layout branch
  • Direction branch
  • Transition branch
  • Failure handling
  • Stale-request guard
  • Loading state
const generation = ++latest;
setLoading(true);
try {
  const [messages, font, assets, code] = await Promise.all([
    loadMessages(culture),
    loadFont(culture, theme),
    loadAssets(theme),
    theme === "midnight" ? import("./orders-list") : null,
  ]);
  if (generation !== latest) return;      // stale
  setMessages(messages);
  setDirection(culture === "ar-EG" ? "rtl" : "ltr");
  setTheme(theme);
  setLayout(pickLayout(culture, theme));
  setAnimation(motion);
} catch {
  // keep whatever was on screen… if nothing above ran yet
} finally {
  setLoading(false);
}
Illustrative sketch, not code from the evaluation

Handed to the engine

  • Experience request
await engine.setExperience({
  culture,
  theme,
  motion,
});
This is the call the Studio makes

This compares where coordination code sits, which is a structural difference. It is not a performance comparison. A carefully written manual controller reaches the same tested safety outcomes; see the Traditional+ baseline on the Evidence page.