FixPortalDocsSimulator
Browse documentation

Architecture

FixPortal separates the public and operator UI, the simulator backend, and content authoring so each can ship on its own cadence without sharing a database or source tree.

Runtime path

The React application is a Vite-built SPA with prerendered public routes. Authenticated commands and queries use REST; live session, order, and traffic updates use SignalR. React Query owns server state, Zustand owns small client preferences, and MSAL supplies Entra authentication in cloud builds.

The .NET 10 backend is an ASP.NET Core minimal API and SignalR host. It owns tenant authorization, SQL Server persistence, simulation policy, and operational endpoints. Its engine and simulation projects wrap QuickFIX/n sessions and turn policy into FIX messages.

The SQL-free Acceptor.Lite project supports the demo venue. Its public demo contract is separate from the operator REST contract.

Keystatic CMScontent/ MDXSPAREST + SignalRBackend API.NET minimal APISQL Servertenant stateFIX EngineQuickFIX/n
The SPA calls the backend over REST and SignalR; the backend persists tenant state to SQL Server and drives FIX sessions through the QuickFIX/n-based engine. Docs and blog content is authored in Keystatic and compiled into the SPA at build time.

Repository boundaries

  • fixportal-simulator-frontend owns the SPA, public pages, docs/blog MDX, generated REST type declarations, and committed consumer contract snapshots.
  • fixportal-simulator-backend owns REST, SignalR, DTO, ATDL, persistence, and FIX-runtime contracts.
  • fixportal-cms is a Keystatic editor over this repository's content/ directory; it owns no content database.
  • fixportal-engine remains a separate reusable FIX-engine product. Do not assume every simulator runtime concern belongs there.

Contracts

The backend publishes OpenAPI, SignalR, TypeScript-shape, and ATDL state-rule snapshots. The frontend commits consumer snapshots under contracts/. npm run generate:rest-types writes REST type declarations to src/api/generated/; it does not generate an HTTP client. Hand-maintained application types in src/api/types.ts form the stable facade consumed by UI code.

The backend's parity tests compare its DTOs with the frontend snapshot, preventing one repository from silently renaming or removing fields.

Content and deployment

Docs and blog entries are MDX compiled into the released frontend. A content change therefore goes through frontend build and prerender checks. The content workflow composes current content with an already released application version, then publishes the resulting static site. Merging an edit does not mutate a live database.

Theme persistence

The published site theme lives in one PlatformSettings row keyed theme_overrides, holding a JSON blob. Saved theme presets live in their own ThemePresets table. Only an unpublished draft touches the browser: it sits in localStorage and is merged over the fetched published theme on boot. White-label snapshot builds skip the runtime fetch and bake the published theme into the static build instead.

BrowserlocalStorage draftThemeStoreProvidermerge on boot/api/theme/globalGET / PUTPlatformSettingsrow: theme_overridesThemePresetstable: saved presets
A published theme lives in one PlatformSettings row; saved presets live in their own ThemePresets table. Only an unpublished draft touches the browser, merged over the fetched published theme on boot.

Security boundaries

Tenant identity is enforced by the backend, not trusted from browser state. Customer builds are generated from the same source with site-specific assets and exclusions. Brand-leak tests, auth gates, and server authorization are separate controls; none substitutes for another.

Updated 2026-09-10 · Edit on GitHub