Prox OS Docs
Architecture

Build and Rendering Pipeline

Explain why the **OS Shell** uses Rsbuild/Rspack, how that differs from other apps in the monorepo, and how React 18 development behavior should influence shell

Purpose

Explain why the OS Shell uses Rsbuild/Rspack, how that differs from other apps in the monorepo, and how React 18 development behavior should influence shell code. For deployable app inventory, see monorepo-workspace-guide.md.

Current Status

SurfaceBuild toolConfig
OS ShellRsbuild (Rspack)apps/os-shell/rsbuild.config.ts
Founder siteViteapps/esmadrider-me
Docs siteNext.js (Fumadocs)apps/docs/next.config.mjs
UI workshopStorybookapps/ui-workshop
API workerWrangler + bundlerapps/api-worker/wrangler.jsonc
packages/*Consumed as TS sourcepackage tsconfig only

Not implemented: Module Federation, qiankun, or runtime-loaded remote micro-frontends in production. Treat those as future direction only.

Why Rsbuild for the Shell

Context: The shell is a large, stateful SPA with many lazy boundaries (apps, iframes), long dev sessions, and strict bundle governance.

Decision: Use Rsbuild on Rspack for apps/os-shell.

Practical benefits for this repo:

  1. Dev feedback — fast rebuild loop for shell chrome and window layer work.
  2. Production bundling — code splitting and asset pipeline suitable for Cloudflare Pages deploy (pnpm build:os, deploy:os).
  3. Tooling alignment — webpack/Rspack ecosystem fits future advanced splitting if needed.
  4. Monorepo consumption — workspace packages resolve through the shell bundler without each package needing its own app build.

What we are not claiming: Rsbuild is mandatory for every Próx app. Standalone or iframe apps may use Vite or another bundler when they deploy outside the shell bundle.

Shell vs App Build Freedom

LayerBuild ownerNotes
Shell chrome, window host, registryapps/os-shell RsbuildSingle deploy artifact
packages/os-appsCompiled into shell via importsNo separate production URL for package apps today
local-module shell appsSame shell bundlee.g. keyboard shortcuts, display options
Iframe appsGuest origin builds itselfpackages/app-registry supplies dev/prod URLs
Future standalone appOwn apps/<name> buildRegisters as iframe or isolated host per manifest

Anti-pattern: Importing apps/os-shell/src/shell/** from an iframe guest or from packages/os-apps.

React 18 and StrictMode

Current: apps/os-shell/src/index.tsx wraps the tree in <React.StrictMode>.

Concurrent mindset: Prefer transitions and non-blocking updates for heavy UI; avoid assuming synchronous mount-only side effects.

StrictMode in development: Effects and certain lifecycles may run twice. Shell code must:

  • Register and clean up listeners in effect cleanups.
  • Guard store hydration so duplicate runs do not corrupt layout.
  • Avoid “fixing” StrictMode by removing it without fixing root cause.

Related: Boot gradient application runs before createRoot in applyBootShellAppearance() so the loading screen matches persisted theme without relying on a single effect pass.

App Runtime vs Bundle

Runtime kinds (from manifests) do not always equal separate bundles:

Runtime kindBundle behavior (current)
os-packageEager or lazy chunk via shell import graph
local-moduleShell bundle
iframeSeparate origin; sandboxed in AppWindow
route-app / isolated-appPlanned hosts; contract types exist

Iframe apps (docs, ui-workshop, scalar, api explorer, esmadrider-me) load on demand when a window opens — they do not all ship inside the shell JS payload.

Future Direction (not shipped)

  • Module Federation or similar for independently versioned app bundles.
  • Shared vendor chunk policy across shell and first-party apps.
  • SSR for shell — not current; shell assumes browser OS.

Document any adoption here and in core-architecture-thinking.md when code lands.

On this page