Application surfaces vs platform backbone
Tier: Public
Status: Decision-of-record 2026-05-28 (terminology + layering; no new RFC)
Audience: core team, module authors, self-hosting operators, anyone asking "where does backend live?" or "do we need admin vs storefront?"
Builds on: PLATFORM-ARCHITECTURE.md §1.1, §2, §4.0–§4.2; REPOSITORY-STRUCTURE.md §2; RFC-0001 §8 (Decision F); ROADMAP.md standing principles
Disclaimer. Clarifies vocabulary and audience boundaries already committed elsewhere. Does not allocate a new canonical module, does not introduce
@umbraculum/coreas a package, and does not change the one-shell / one-AI-context principle.
1. Summary
| Question | Short answer |
|---|---|
| What is the platform backbone? | Horizontal platform services (auth, workspace, billing, AI, rendering, i18n, navigation primitives) + services/api as the single API monolith + @umbraculum/module-sdk as the module registration contract. |
| What is a backend in this repo? | Usually services/api (layer 2). Sometimes the whole horizontal platform. Rarely "Drupal admin" — that phrase overloads operator UI with API service. |
| Drupal-style admin vs customer frontend? | Not the model for PIM / WMS / MRP / CRP / CRM or for brewery today. Operator modules share one workspace-member shell. Shopper-facing surfaces (if any) are separate apps. |
| How do you "configure" a public operational product? | Install canonical modules + vertical configuration + workspace entitlements — not by theming a second backend inside apps/web. |
Is @umbraculum/core the backbone? | No. That npm name is reserved and unused. The backbone SDK is @umbraculum/module-sdk plus horizontal packages (§5). |
2. Four layers (not "backend vs frontend")
| Layer | Role | Examples in tree |
|---|---|---|
| Platform backbone | Cross-cutting services every module consumes (RFC-0001 §8.2); single source of truth for tenancy and AI context | services/api, @umbraculum/contracts, @umbraculum/module-sdk, @umbraculum/ui, @umbraculum/navigation, @umbraculum/rendering, … |
| Canonical modules | Peer operational domains (flat SAP-style decomposition, not nested under "manufacturing") | automation, pim (shipped); mrp, crp (alpha read-only shipped); wms, crm (open doors) |
| Vertical configuration | Seed data, prompts, vertical UI — consumes canonicals, does not replace them | brewery (reference tier-6 configuration) — web slice under apps/web/app/[locale]/(brewery)/ (β layout complete for recipes, 2026-06) |
| Application surfaces | Deployable UIs or sites for a specific audience | apps/web + apps/native (operators); Ubuntu Touch via Click Morph webapp wrapper over apps/web (ubuntu-touch-shell-strategy.md); umbraculum-brochure (public orientation); future storefront = separate apps/* |
Repository layers vs product layers. REPOSITORY-STRUCTURE.md names layer 1 Applications (apps/*) and layer 2 Services (services/*). That is spatial (where code lives), not Drupal's merchant/customer split. Both web and native are operator applications talking to the same API.
3. Terminology glossary
Use these terms in reviews and plans to avoid talking past each other. For onboarding terms (vertical, canonical, brewery reference vertical, module taxonomy): GLOSSARY.md.
| Term | Meaning | Do not confuse with |
|---|---|---|
| API service | HTTP monolith: routes, Prisma, jobs | Operator UI, "admin theme" |
| Horizontal platform | Auth, workspace, billing, AI orchestrator, rendering, notifications boundary, … | A single package named core |
| Workspace web UI | Federated web shell (apps/web) workspace members use daily | Storefront, brochure site; not “all native binaries” |
| Workspace-member app | Primarily workspace web UI — one web shell, one AI workspace context (ROADMAP) | B2C shopper app; not one mega-native shell |
| Native purpose-built binary | One Expo store app at apps/native/<app-code>/ (brew-day, future floor/scanner apps) | @umbraculum/native-shell package; apps/web |
| Native app composition | Which module native slices a binary registers at build time (registerNativeModule subset) | Installation profile listing every server module in one app |
| Module registration | Boot-time declaration via registerModule() / registerWebModule() / registerNativeModule() | Runtime shared layout registration (partially deferred — see §5) |
| Public surface (marketing) | Static orientation HTML | Operational "public API" |
| Storefront / commerce (future) | Separate deployable; read-only consumer of PIM/CRM master data | PIM admin UI |
4. Drupal-style vs ERP-style
4.1 Drupal-style (usually not this project)
- Merchant configures catalog in admin backend
- Customer shops on themed frontend
- Two audiences, often two apps, shared CMS core
4.2 Umbraculum-style (committed)
- Workspace members (planners, brewers, warehouse staff, admins) use one web shell (
apps/web) with federated module routes — the ecosystem can grow large on web (Odoo-class operator UI is in scope on this surface) - Native ships many purpose-built binaries (
apps/native/<app-code>/), each composed from a subset of module native slices — not one native deployable that mirrors every web route (RFC-0011 Decision C;installation-profile.md§ Web vs native) - Canonical modules are operator systems (Akeneo / SAP / Odoo class admin), not storefronts
- AI consultant requires workspace-scope context on web + API — multiple native task apps do not split that context; a single mega-native shell is not required and is not the target shape
Standing principle (ROADMAP.md) — read web vs native:
One audience per app. Workspace-member modules share one web shell. Shopper-facing surfaces (if any) are separate apps. Native uses separate store binaries where mobile form factor is intrinsic (offline, scanning, floor input) — see
apps/native/README.md.
4.3 Where Drupal does apply — the optional edge
| Surface | Audience | In repo today |
|---|---|---|
| PIM product admin | Workspace member | (pim)/ routes in apps/web |
| Channel feed / CSV export | Downstream system | PIM + RFC-0007 rendering |
| Shopper storefront | Anonymous / customer | Not in repo; explicitly separate app if pursued |
| Marketing site | Evaluator / contributor | umbraculum-brochure (static; not operational) |
PIM boundary (canonical-pim-module-surface.md §3.2): master product data is canonical; storefront projections belong to a sibling commerce module, not inside PIM.
5. Module SDK vs @umbraculum/core vs shell composition
5.1 Yes — the "core SDK" already exists
In governance and npm terms, the module registration spine is shipped:
| Package | Tier | Role |
|---|---|---|
@umbraculum/module-sdk | 2 (MIT) | registerModule(), registerWebModule(), registerNativeModule(), reserved codes, ValidatedSchema<T>, document-template types |
@umbraculum/ai-tool-sdk | 2 (MIT) | AI tool contract types |
@umbraculum/i18n-keys | 2 (MIT) | Module nav / message-key conventions |
Third-party modules pin these — they are the public "how you plug into the platform" contract (MODULES.md §3.3, RFC-0001 tier 2).
The SDK is contract + boot-time registry, not the API implementation:
| Concern | Owner |
|---|---|
| Fastify routes, Prisma, orchestrator, billing webhooks | services/api |
| Registration shape, collision detection, nav metadata types | @umbraculum/module-sdk |
Tamagui primitives, route IDs, useT, api-client | Other horizontal packages |
5.2 What @umbraculum/core is not
During the @brewery/* → @umbraculum/* scope migration, @brewery/core (brewing math) was renamed to @umbraculum/brewery-core — deliberately not @umbraculum/core — so "core" does not read as "everything shared" (brewery-scope-migration-plan.md §1.3).
There is no @umbraculum/core package today. The name remains reserved; creating it as a grab-bag of shared code would recreate the trap the migration avoided.
5.3 Shell composition — related problem, different home
Some runtime shell concerns are partially extracted:
- Registry-driven primary nav —
composeWebSharedLayoutNavItems()in@umbraculum/module-sdkreadsregisterWebModule({ navEntries })metadata fromBUILTIN_WEB_MODULE_REGISTRATIONS;PrimaryNav.tsxreceives composed items from the server layout. - Platform-owned URL segments —
registerPlatformSegments.tslives inapps/webtoday. - Entitlement-gated nav / upgrade affordances — tied to
WorkspaceBillingand futureWorkspaceBillingAddon(PLATFORM-ARCHITECTURE.md §3.6–§3.7).
These are operator-shell composition problems. Reasonable future homes (pick one when the debt hurts — no commitment now):
- Stay in
apps/web/apps/nativeuntil a second shell consumer exists - Extract shared shell helpers to a new horizontal package (e.g.
@umbraculum/shell— name illustrative only) - Extend
@umbraculum/navigationwith registry-aware composition helpers
They should not become a second API, duplicate module-sdk, or hold domain logic. @umbraculum/module-sdk remains the registration contract; any future shell package would consume it, same as apps/web does.
6. Worked examples
6.1 Brewery workspace (today)
| Piece | Classification |
|---|---|
| Recipe editor, brew-day flows | Vertical configuration UI in workspace web UI |
/auth/*, workspace switcher | Horizontal platform |
services/api recipe routes | API service (brewery-vertical routes today; β-layout under modules/brewery/) |
| Brochure at umbraculum.dev | Layer 4 marketing — not operational backend |
| Hypothetical beer shop | Layer 4 separate app — would consume PIM/CRM APIs, not live inside (brewery)/ |
Brewery operators are the users of apps/web / apps/native. There is no in-repo B2C storefront; native exists for offline brew-day (form factor), not for shoppers.
6.2 PIM-only workspace (future)
A cosmetics company using only pim + platform horizontal services:
- Operators use
(pim)/products,(pim)/categories, … in the same shell as any other installed module - No WMS/MRP required for a minimal deployment
- Shopify storefront (if built) = separate app reading channel feeds / APIs — not "PIM frontend theme"
6.3 Configuring a hosted product
To offer "Umbraculum hosted for breweries" or "hosted PIM":
- Enable modules + vertical seed (brewery configuration or PIM-only)
- Set workspace billing tier and (future) per-module add-ons
- Assign workspace members and roles
- Optionally operate a separate marketing or commerce app — not by forking the workspace web UI into "admin" vs "store"
7. Cross-references
- PLATFORM-ARCHITECTURE.md — vision, audit, target module model
- REPOSITORY-STRUCTURE.md — five-layer monorepo map
- MODULES.md — ecosystem entry + horizontal package catalog
- packages/sdk/module-sdk/README.md — registration contract (the backbone SDK)
- design/web-route-group-audit.md — URL segment ownership +
registerWebModule - design/canonical-native-platform-surface.md — native shell obligations
- design/ubuntu-touch-shell-strategy.md — Ubuntu Touch Morph webapp wrapper (web slice + Click packaging; online-first)
- RFC-0001 §8.2 — consumption contract (what modules must not reimplement)