Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt

Use this file to discover all available pages before exploring further.

Status: Inert scaffolding committed; activation requires project-owner action Owner: Platform Architecture (technical) + Jeremy Bloom (Vercel dashboard owner) Phase: 3 of docs/recommendations/DEV_VELOCITY_AND_ARCHITECTURE_PLAN_2026-04-22.md (lands via PR #137) ADRs: ADR-008 (preserved), ADR-013 (amendment proposed in ADR-017)

What this PR ships

  • microfrontends.json at the repo root — the proposed split. Two applications:
    • encoreos-app (default; receives every un-routed path; today this is the entire app)
    • encoreos-public (peeled off: /auth, /employee-setup, /pending-activation, /pm/kiosk/:siteId/*, /portal/*, /p/:token, /packet/:token, /gr/whistleblower-report, /chatbot/widget)
  • Turborepo workspace mapping: Turborepo resolves microfrontends.json application keys to npm workspace packages by matching the application key to package.json name. The keys encoreos-app / encoreos-public therefore have minimal placeholder packages at packages/encoreos-app and packages/encoreos-public (private, no source — the real app remains the root Vite SPA). When Phase 3 splits into real deployables, replace these placeholders with actual package roots or add packageName per the Turborepo microfrontends schema.
  • scripts/audit/validate-microfrontends-config.ts — fast structural validator (kebab-case names, single default app, paths start with /, literal-overlap detection, soft check that paths exist in src/App.tsx / src/routes/). Wired to npm run audit:microfrontends.
  • docs/architecture/decisions/ADR-017-microfrontends-pwa-scoping.md — formal ADR amending ADR-013 to handle per-zone PWA scopes.
  • This runbook — step-by-step activation instructions, env-var layout, CI wiring, Playwright proxy invocation, rollback plan.
What is intentionally NOT shipped:
  • The @vercel/microfrontends Vite plugin is not installed and not wired into vite.config.ts. Adding it without a corresponding Vercel project + microfrontends group does nothing useful and would only add a transitive dep. The activation steps below cover the install.
  • No new Vercel projects exist yet. Creation is a dashboard action only a project owner can perform.
  • The microfrontends.json file is inert until a Vercel Microfrontends Group exists in the Vercel team and the application names there match the names in this file.
This is intentional: by the time someone is ready to flip the switch, the design choices, validation, and PWA strategy are all already in code review.
⚠️ Editing microfrontends.json — strict-keys gotcha Both Turborepo (turbo 2.9+) and the Vercel runtime parse microfrontends.json and reject any unknown keys — including JSON-comment-style fields like _comment, _comment_*, etc. If an unknown key slips in, turbo run … aborts with Unable to parse JSON: Found an unknown key … and every Turborepo task fails before it starts. This regression was introduced once already (PR #145, fixed in the verification PR) when this runbook’s author shipped Vercel-style _comment_* keys. Allowed top-level keys: $schema, applications, options. Allowed per-application keys: routing, development, packageName, assetPrefix. Allowed per-routing-rule keys: group, paths, flag. Allowed development keys: fallback, local, task. Keep narrative notes here (in this runbook), not in microfrontends.json. The npm run audit:microfrontends validator now hard-fails on unknown keys to prevent this from ever shipping again.

Activation overview (project-owner steps)

Activation is sequenced in five phases. Steps 1–2 are dashboard / infrastructure actions; steps 3–5 are code PRs.
StepWhoTimeReversible?
1. Create the second Vercel project (encoreos-public)Project owner~5 mintrivially (delete project)
2. Create the Microfrontends Group + add both projectsProject owner~5 mintrivially (delete group)
3. Land the wiring PR (Vite plugin install + plugin registration)Engineer + project owner~half-dayrevert PR
4. Promote a preview build with the new routing liveProject owner~10 minVercel Instant Rollback (one-click)
5. Production cutoverProject owner~5 min after preview soakVercel Instant Rollback
If anything looks off at any step, stop. The microfrontends.json file in prod does nothing until the Vercel Group is wired up; rolling forward in code is decoupled from rolling forward in production routing.

Step 1 — Create the second Vercel project

In the Vercel dashboard:
  1. Add New… → Project → Continue with this Repository (Encore-OS/encoreos).
  2. Project name: encoreos-public.
  3. Framework preset: Vite. Root directory: . (same monorepo root).
  4. Build & Development Settings:
    • Build command: npm run build (same as the main project; the Vite plugin handles asset prefixing once installed).
    • Output directory: dist.
    • Install command: npm ci --legacy-peer-deps.
  5. Environment variables: none for now. Build-time Supabase URL/key are statically defined in vite.config.ts per VERCEL_PROJECT_ID (see AGENTS.md § Cursor Cloud caveats and docs/development/VERCEL_ENV_REMOVAL_EXECUTION_2026-04-20.md).
  6. Important: before adding encoreos-public’s prj_* ID to vite.config.ts’s VERCEL_PROJECT_TO_SUPABASE map, decide which Supabase target it points to. Recommend same as the parent project’s environment so encoreos_dev’s public zone hits dev Supabase, and encoreos_prod’s public zone hits prod Supabase.
  7. Do not deploy yet. Pause auto-deploy under Settings → Git → Deploy Hooks if the project tries to build immediately.
Repeat for any additional zones beyond the recommended split (the recommendations doc § 5.5 suggests a possible second wave: encoreos-clinical for /cl/* + /pm/* — only do this if Phase 1+2 measurements show it’s still needed).

Step 2 — Create the Microfrontends Group

In the Vercel dashboard:
  1. Team Settings → Microfrontends → Create Group.
  2. Group name: encoreos.
  3. Default application: encoreos-app (the original project).
  4. Add encoreos-public to the group.
  5. Fallback environment: Same Environment (so preview builds without a matching encoreos-public build fall back to the production deployment of encoreos-public rather than the production deployment of encoreos-app).
  6. Confirm pricing acknowledgement: 2 microfrontend projects per group are included on Pro; the proposed split fits in the free tier as long as we never add a third zone.
The group will not change behavior until the next deployment of the default application that contains a microfrontends.json file. Since this PR commits microfrontends.json already, the next merge to prod after activation will start routing.
⚠️ Sequence matters. Create the group before merging the wiring PR (step 3). If the wiring PR merges first while the group does not exist, Vercel logs a deployment warning but does no harm — the file is treated as inert.

Step 3 — Land the wiring PR

This is a small follow-up PR — open it once steps 1 and 2 are complete:
# Install the Vite plugin (one new dep)
npm install --save @vercel/microfrontends --legacy-peer-deps
Add to vite.config.ts:
import { microfrontends } from '@vercel/microfrontends/experimental/vite';

// inside the plugins array:
microfrontends({
  // The Vite plugin auto-detects the application name from VERCEL_PROJECT_ID
  // matched against the Vercel project names in microfrontends.json.
  // No options needed for the basic case.
}),
Update package.json:
{
  "scripts": {
    "mf:proxy": "microfrontends proxy --local-apps encoreos-app encoreos-public",
    "mf:port": "microfrontends port"
  }
}
Verify locally:
npm run audit:microfrontends    # validate the config
npm run build                   # confirm Vite plugin doesn't break the build
npm run mf:proxy                # in one terminal
npm run dev                     # in another
# Visit the proxy URL printed by `mf:proxy` (typically http://localhost:3024)
# Try /, /auth, /pm/kiosk/test, /portal/login — all should resolve
The wiring PR should also:
  • Update .github/workflows/build.yml to run npm run audit:microfrontends as a blocking step.
  • Update .github/workflows/build.yml to set MFE_DISABLE_LOCAL_PROXY_REWRITE=1 so existing E2E tests that hit individual project URLs continue to work.
  • Add TURBO_TOKEN / TURBO_TEAM GitHub Actions secrets if you also want Vercel Remote Cache active for the encoreos-public project (see docs/development/TURBOREPO_USAGE.md).

Step 4 — Preview soak

  1. After the wiring PR merges, open a fresh PR (any small change). Vercel will build BOTH encoreos-app AND encoreos-public for the preview commit.
  2. Visit the preview URL of encoreos-app. You should see:
    • / → main app (HR, etc.) — same as today.
    • /auth → routed to encoreos-public. Look for the small “M” badge on the deployment page (Vercel Microfrontends indicator).
    • /pm/kiosk/test → routed to encoreos-public.
  3. Open the Vercel Toolbar on the preview, expand the Microfrontends Panel, and confirm the routing table matches microfrontends.json.
  4. Run the smoke E2E suite against the preview:
    npm run test:e2e:smoke
    
    If any test asserts a hard navigation between /auth and any authenticated route, expect it to still pass but to take an extra ~200 ms (the cross-zone hard-navigation cost). If any test relies on shared client state across zones, it will fail — those tests need to be rewritten or marked skip-on-microfrontends.
Soak the preview for at least 24 hours before proceeding. Watch the Vercel Speed Insights dashboard for the preview to confirm INP/LCP are not regressing on routes that cross zones.

Step 5 — Production cutover

  1. Promote the soaked preview deployment to production via the Vercel dashboard’s “Promote to Production” button.
  2. Watch Sentry for new error volume in the first 30 minutes — particularly:
    • Hydration mismatches (none expected; Vite SPA, no SSR).
    • Auth-redirect loops (the /auth zone now lives behind microfrontends path routing; verify useCurrentUser still works after the hard-nav from /auth/).
    • PWA service worker registration errors (covered by ADR-017; both zones must agree on SW scope).
  3. If anything looks off, hit Vercel Instant Rollback on the default application (encoreos-app). Microfrontends routing reverts to the previous microfrontends.json (which, before this whole rollout, was implicit — single app — so the old behavior is fully restored).

Local development

Once steps 1–3 are complete, the local DX is:
# Terminal 1: run the local proxy that knows about the routing config
npm run mf:proxy

# Terminal 2: run the dev server for the zone you're working on
npm run dev    # encoreos-app
# OR
npm run dev    # if you're working on encoreos-public, run the same; the
               # plugin auto-targets based on VERCEL_PROJECT_ID, defaulting to encoreos-app

# Visit the proxy URL printed in terminal 1 (typically http://localhost:3024)
The proxy routes requests for zones you are NOT running locally to the production fallback — so you only need to run one zone at a time. To hit the local zone directly, bypassing the proxy, set MFE_DISABLE_LOCAL_PROXY_REWRITE=1.

Environment variable layout

VariableWhere setUsed for
VERCEL_PROJECT_IDSet automatically by Vercel at build timevite.config.ts uses this to pick dev vs prod Supabase target. Must be added to VERCEL_PROJECT_TO_SUPABASE for the new encoreos-public project IDs (one for dev, one for prod) before the first deploy.
MFE_DISABLE_LOCAL_PROXY_REWRITELocal .env onlyBypasses the local proxy when set to 1. Useful for E2E tests that hit a specific zone directly.
MFE_DEBUGLocal .env onlyVerbose logging from the proxy and the Vite plugin.
TURBO_TOKEN / TURBO_TEAMGitHub Actions secrets + dashboardVercel Remote Cache for both encoreos-app and encoreos-public. Optional but recommended.
AUTOMATION_BYPASS_ENCOREOS_PUBLICGitHub Actions secretsIf encoreos-public ends up behind Vercel Deployment Protection, this is the Protection-Bypass-for-Automation token. Documented in Vercel’s microfrontends local-development docs.
Do not add new project-level environment variables in the Vercel dashboard for the public client config (Supabase URL, etc.). The constitution / AGENTS.md enforces that those stay in vite.config.ts per VERCEL_PROJECT_ID.

Rollback plan

ScenarioAction
Bug in production routingVercel Instant Rollback on encoreos-app (or encoreos-public) — restores the routing of the previous deployment.
Need to roll back the entire microfrontends schemeVercel dashboard → Microfrontends → delete the group. The default app reverts to receiving every path, exactly as today. The microfrontends.json file in the repo becomes inert.
Need to revert the wiring PRgit revert <wiring-PR-merge-commit>; the Vite plugin disappears; subsequent builds of encoreos-app ignore microfrontends.json. The microfrontends group can be deleted at leisure.
The whole stack is designed so each layer can be rolled back independently. The riskiest operation is the first promotion to production (step 5); after that, every change is incremental and well-contained.

What this scaffolding does NOT solve

The recommendations doc (§ 3.5–3.7) calls out four hard problems with microfrontends on a Vite SPA. They remain unsolved by this PR — they’re handled at activation time:
  1. Cross-zone shared state. OrganizationProvider, QueryClientProvider, Sentry, Sonner, nuqs, and the PWA service worker all bootstrap per zone. A user moving between /auth and the authenticated app pays a cold cache penalty. Mitigations to evaluate at step 4: BroadcastChannel for cross-zone state sync, or accept the cold cache (the public→authenticated transition only happens at sign-in time anyway).
  2. PWA scope. Each Vercel project generates its own service worker. Only one can install at scope /. ADR-017 (companion to this PR) defines the per-zone scope strategy: encoreos-app keeps scope: '/'; encoreos-public either uses sub-scopes (scope: '/portal/', etc.) or disables the SW for that zone entirely.
  3. Dependency duplication. Each zone bundles its own React, Radix, Supabase client. For a 2-zone split this adds ~300 KB of duplicate vendor code on first hard-nav between zones. Acceptable for the proposed split (the public zone is a thin set of pages); not acceptable for a 12-zone split.
  4. Cross-zone link prefetching. Vercel’s PrefetchCrossZoneLinks is Next.js only. Any prefetch-on-hover behavior we want has to be implemented manually using Chromium Speculation Rules, the same way Vercel.com does it.

See also