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
| Layer | Implementation |
|---|---|
| Frontend | React 19, built as a single-page application and bundled with Vite, with Tailwind CSS for styling |
| Server functions | Serverless functions on Vercel — all AI calls, exports and administration actions run through them |
| Database | Supabase (PostgreSQL) with row-level security on every table |
| Vector search | pgvector inside the same database — no separate vector service |
| Authentication | Supabase Auth, by invitation only |
| Document rendering | Server-side headless browser for PDF export |
| Error monitoring | Sentry, 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
| Component | How it is safeguarded |
|---|---|
| Database migrations | one 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 tests | on every change, mandatory before merging; 2,816 test files |
| Test suites for tenant isolation | 134 series, run on every change that touches the database and every night against a real database |
| Nightly checks | full journeys through the application, the isolation test, the model list and the scan for vulnerable packages |
| Tables | 162 in the public schema, with row-level security on every table |
| Architecture decisions | 39, with alternatives and the conditions for reconsideration |