Web codebase split — apps/web → apps/web-snow + apps/web-summaryto
Web codebase split — deferred task
Section titled “Web codebase split — deferred task”Status: Deferred to Phase 4 of the summary.to execution plan.
Trigger to execute: summary.to needs an independent release cadence — i.e. when shipping a summary.to change is blocked, slowed, or risk-coupled to SNOW releases (or vice versa). Until then, the single apps/web codebase with host-routed sub-apps is sufficient.
Current state
Section titled “Current state”| Surface | Brand | Service | Codebase |
|---|---|---|---|
platform.snowmed.health, app.snowmed.io, snowmed.health | snowmed | snow_web | apps/web |
summarisenow.snowmed.health | summarisenow | snow_web | apps/web |
*.summary.to, summary.to/Dr.X | summary_to | snow_web | apps/web |
SNOW is the engine (internal), not a customer-facing brand. The B2B brand is snowmed.
All three brands deploy out of one Vercel project. Host-routing branches at the React root into per-brand subtrees.
Target state (when triggered)
Section titled “Target state (when triggered)”| Surface | Brand | New service | New codebase |
|---|---|---|---|
platform.snowmed.health, app.snowmed.io, snowmed.health, summarisenow.snowmed.health | snowmed, summarisenow | snow_web | apps/web-snow |
*.summary.to | summary_to | summaryto_web | apps/web-summaryto |
Two Vercel projects. Independent CI, bundles, cache, CSP/headers.
Why defer
Section titled “Why defer”| Reason to do it now | Counter |
|---|---|
| Cleaner brand isolation | Already achieved via host-routed subtrees |
| Smaller bundles | Not yet a measured problem |
| Independent deploys | Not yet a release-cadence conflict |
| Easier carve-out for entity split | Carve-out optionality preserved via brand-tagged P&L; physical split not required yet |
| Reason to defer | Cost if done now |
|---|---|
| Duplicate auth wiring | ~1 week eng |
| Shared component package needed | Refactor apps/web/src/components → packages/ui-core; ~1 week |
| ×2 CI/CD pipelines | Ongoing maintenance + slower local DX |
| ×2 Vercel cache, ×2 cold-start budget | Cost + perf surface area |
Pre-work (do now, while still one codebase)
Section titled “Pre-work (do now, while still one codebase)”To make the future split a near-mechanical lift:
- Branch on host at React root:
<SnowApp />/<SumNowApp />/<SummaryToApp />subtrees with their own routers and layouts. - Move shared primitives (forms, file upload, auth hooks, theme) to
packages/ui-coreeven within the monorepo — no../../web/srcimports across subtrees. - Brand-tag every emitted event (
brandaxis, distinct fromserviceaxis). See brand-vs-service taxonomy. - Independent visual systems per brand: no shared CSS variables or design tokens leaking across subtrees.
- Per-brand environment-variable convention:
VITE_SNOW_*,VITE_SUMNOW_*,VITE_SUMMARYTO_*.
Execution plan (when triggered)
Section titled “Execution plan (when triggered)”- Create
apps/web-summarytofrom the<SummaryToApp />subtree. Pull only the imports it actually uses. - Lift shared deps into
packages/ui-coreif not already. - New Vercel project
snow-web-summaryto; bindsummary.toapex + all*.summary.tosubdomains. - Rename existing Vercel project’s domain bindings to drop
*.summary.to. - Update API CORS allowlist to source-of-truth (no per-codebase config).
- Cut over via DNS — both projects can serve in parallel for a soak period.
- Drop the
<SummaryToApp />branch fromapps/webonce traffic confirms.
Definition of done
Section titled “Definition of done”-
summary.toand*.summary.toresolve toapps/web-summarytoVercel project -
apps/webno longer contains summary.to-specific code paths - CI builds both projects independently
- No regression in auth, upload, or share flows on either brand
- One full release cycle each ships independently without coordination
See also
Section titled “See also”- Brand vs service taxonomy
- summary.to execution plan — Phase 4
- External presentation policy (house-of-brands)