Frontend architecture
The Atlas Console is a React 18 + TypeScript single-page application built with Vite. It uses the Palantir Blueprint 5 design system in dark mode, TanStack React Query for server state, and Zustand for client UI state. Authentication and tenant resolution are handled by provider components at the root.
Provider tree
TenantProvider resolves the tenant from the URL slug (GET /api/tenants/resolve), AuthProvider
creates a Keycloak instance for that tenant's realm, and the React Query client is scoped to the
tenantId so cached data can never bleed between tenants.
Directory roles
| Directory | Role |
|---|---|
api/ | Axios client with auth interceptors, query-key factory, typed API modules |
auth/ | AuthProvider, TenantProvider, Keycloak wrapper, auth pages |
components/ | Reusable components grouped by feature (layout, report, risk, graph, evaluation, studio, …) |
hooks/ | Domain hooks wrapping React Query (useInvestigations, useCompanies, …) |
pages/ | Route-level pages |
stores/ | Zustand stores (evaluationStore, mappingStore, previewStore) |
config/, constants/, content/, types/, utils/ | Configuration, static data, help text, types, helpers |
State & data flow
- Server state flows through React Query. Hooks like
useInvestigations(filters)build a tenant-prefixed query key and call typed API modules. Active investigations poll every 5s. - Client state (matrix selection, mapping wires, comparison mode) lives in Zustand stores.
Every store implements
.reset()and is reset on tenant change, mirroring the backend's tenant isolation. - Cross-cutting context carries the current user, tenant, and sidebar collapse state.
Pages and features
Highlights:
- ReportView renders an investigation as tabs — risk gauge, findings, evidence bundle,
ontology graph, lineage, and workflow timeline — backed by
useReport(id)(which handles202 Acceptedwhile a report is still generating). See Reporting. - RiskCenter offers portfolio, dashboard, table, and network views over portfolio risk, using Recharts and a Cytoscape network graph.
- GraphExplorer / OntologyExplorer visualise the knowledge graph and ontology schema with Cytoscape.
- Compliance Studio is where engineers configure data sources, ontology field mappings (the drag-and-drop MappingDesigner), risk matrices, evaluations, and settings.
Authentication & tenant resolution
The Vite dev server proxies /api to the backend and /realms, /resources to Keycloak so that
cookies stay same-origin; nginx does the equivalent in production. See
Security & multi-tenancy for the matching backend enforcement.
Deep dive: data, caching, and tenant isolation in the UI
This reflects frontend/src/ — queryClient.ts, api/client.ts, hooks/, stores/,
auth/.
React Query configuration
| Setting | Value |
|---|---|
staleTime (default) | 5 minutes |
gcTime | 24 hours |
retry | 1 |
refetchOnWindowFocus | false |
| Persistent cache | localStorage, key osint-query-cache-{tenantId}, maxAge 24h |
The cache is persisted per tenant and every query key is prefixed with tenantId, so a tenant
switch can never surface another tenant's cached data.
Auth on every request
The token lives in memory (never localStorage), is proactively refreshed on a 60s margin
(auto-refresh every 30s), and a 401 triggers a single refresh-and-replay before redirecting to
login. FormData requests drop the Content-Type header so the browser sets the multipart boundary.
Polling patterns
useInvestigations/useInvestigationpoll every 5s while any investigation ispending/in_progress, then stop.useReporthandles202 Acceptedby retrying up to 60× at 5s intervals (≈5 minutes) — the report is generating server-side.
Stores reset on tenant change
Each Zustand store implements .reset(); TenantProvider calls all of them (and clears React
Query) the moment the tenantId changes — the frontend mirror of backend tenant isolation.
Graph visualization
Report and explorer graphs transform API data into Cytoscape elements, tagging nodes with type and
risk classes (legalentity, person, address, pep, sanctioned, center) and edges with
mapped relationship types (OWNS, DIRECTS, REGISTERED_AT). Layouts available: fcose, dagre,
cose-bilkent, breadthfirst (rooted at center nodes), and force.
To add UI, see Add a frontend feature.