service

RIO Web App

The React + TypeScript frontend. Consumes every backend service through the single App Layer gateway, authenticating with Cognito OIDC.

Service

Service Overview

The user-facing application. React 18 + TypeScript on Vite 6, with TailwindCSS for styling and ApexCharts for visualisation.

It is included in this catalog because it is the platform’s only human-facing consumer — knowing which endpoints it actually calls tells you which parts of the backend are genuinely in use.

Notably, it is built as a Module Federation remote (@originjs/vite-plugin-federation), exposed as rioUi with a ./bootstrap entry and a default base path of /rio/. It is designed to be mounted inside a host shell rather than served standalone.

One base URL, one front door

Every request goes through a single environment variable, VITE_API_BASE_URL (src/lib/env.ts:31), pointing at the Application Layer Service.

src/lib/httpClient.ts is the only client: it attaches Authorization: Bearer <token> and X-User-Id, raises a typed ApiError, and redirects to /auth/login on a 401.

There are no per-service hostnames anywhere in src/, which independently confirms that all traffic is funnelled through the gateway.

Authentication is Cognito via react-oidc-context, matching the Lambda authorizer on the gateway side.

Which service each screen actually talks to

Frontend moduleEndpointsBacking service
features/auth/authService.ts/users/tenants, /tenants/{t}/users/{u}Identity
features/admin/api/usersService.ts/tenants/{t}/usersIdentity
features/admin/api/rolesService.ts/tenants/{t}/rolesIdentity
features/admin/api/userGroupsService.ts/tenants/{t}/user-groupsIdentity
features/admin/api/hierarchyService.ts/tenants/{t}/hierarchy, .../actions, .../nodes/{n}Identity
features/admin/api/tagsService.ts/tenants/{t}/tagsIdentity
features/admin/api/regionsService.ts/tenants/{t}/regionsIdentity
features/admin/api/timezonesService.ts/tenants/{t}/timezonesIdentity
features/admin/api/auditService.ts/tenants/{t}/auditsAudit
features/forecast/api/forecastService.ts/tenants/{t}/forecast/*Commit
features/quota/api/quotaService.ts/tenants/{t}/quotas*Commit
features/forecast/api/opportunityService.ts/tenants/{t}/opportunities*Opportunity
features/deal-desk/api/dealDeskBriefService.ts.../quotes*, .../sales-team, .../install-base, /products/discount-benchmarks, /activity/opportunities/{id}/email-summary, .../threadsOpportunity + Activity Signal

Two things worth knowing

One module bypasses the shared client. features/admin/api/auditService.ts builds its URL by hand (${env.apiBaseUrl}/tenants/${tenantId}/audits…, line 137) and calls raw fetch (line 153) instead of going through httpClient. So it does not get the shared 401-redirect or ApiError handling that every other module gets.

Several screens are still fixture-driven. src/mocks/fixtures/ and src/mocks/handlers/ supply mock data for the dashboard, assess, deal desk, exec dashboard, coverage-behind-call, admin console and chart surfaces. Those pages render from fixtures, not from live APIs — so “the UI shows it” is not evidence that an endpoint exists.

It uses no events

The web app has no EventBridge, WebSocket, SSE or GraphQL client. All communication is request / response over HTTPS through the gateway. It also does not call Cube or the MCP server directly.

Event-driven architecture documentation: RIO