Skip to main content

Architecture at a glance

A pragmatically designed multi-tenant SaaS application: one web application, serverless functions for the heavy work, and a Postgres database in which authorisation is enforced at row level.

The stack​

LayerImplementation
FrontendReact 19, built as a single-page application and bundled with Vite, with Tailwind CSS for styling
Server functionsServerless functions on Vercel — all AI calls, exports and administration actions run through them
DatabaseSupabase (PostgreSQL) with row-level security on every table
Vector searchpgvector inside the same database — no separate vector service
AuthenticationSupabase Auth, by invitation only
Document renderingServer-side headless browser for PDF export
Error monitoringSentry, on both the client and the server side

Why this setup​

Two choices deserve an explanation.

All AI calls go through server functions, never from the browser. Keys for AI providers and the database service role exist on the server side only. The browser cannot make an AI call that does not first pass through the platform's own gateway, where authorisation, budget monitoring and prompt resolution take place.

No separate vector database. The embeddings live in the same Postgres as the canvas data. This means the same row-level security applies to searching for evidence as to ordinary data — tenant isolation does not have to be kept consistent in two systems separately.

Environments​

There are two full environments:

  • Staging — a schema copy of production with disposable content. Every database change is proven here first.
  • Production — receives schema changes only through a migration file that has already been applied and verified on staging.

That order is not an agreement but an automated gate in the release pipeline; see Quality and delivery.

Scale of the codebase​

ComponentHow it is safeguarded
Database migrationsone base file of 47,108 lines plus 26 migrations after it (as of 30 October 2026), each a version-controlled file, applied in order and proven on staging first
Component and unit testson every change, mandatory before merging; 2,816 test files
Test suites for tenant isolation134 series, run on every change that touches the database and every night against a real database
Nightly checksfull journeys through the application, the isolation test, the model list and the scan for vulnerable packages
Tables162 in the public schema, with row-level security on every table
Architecture decisions39, with alternatives and the conditions for reconsideration