System Map
The platform is three main pieces plus the services they lean on. Resonance is the face, Foundation is the brain and system of record, and Forth is the legacy system we’re pulling data out of and steadily moving away from.
The map
Section titled “The map”flowchart TD
subgraph client["Client-facing"]
R["Resonance<br/>React + Bun + Vite<br/>client & staff portal"]
end
subgraph core["Core platform"]
F["Foundation<br/>Django + PostgreSQL<br/>system of record"]
PG[("PostgreSQL")]
NATS["NATS JetStream<br/>async pipelines"]
TS["Typesense<br/>search"]
S3["S3 / MinIO<br/>documents"]
end
subgraph legacy["Legacy"]
FORTH["Forth CRM<br/>legacy contact & payment data"]
end
subgraph ext["External services"]
PAY["Payment processors<br/>Unity FI (ACH), Cornerstone, VGS"]
COMMS["Comms<br/>Postmark, Twilio, postal"]
AI["Anthropic Claude<br/>letter classification"]
SENTRY["Sentry"]
CAL["Calendly"]
end
R -->|"REST /api/v1 (session auth)"| F
R --> SENTRY
R --> CAL
F --- PG
F --- NATS
F --- TS
F --- S3
F -->|"one-way pull / sync"| FORTH
F --> PAY
F --> COMMS
F --> AI
How to read it
Section titled “How to read it”- Resonance → Foundation. The portal is a thin client. It holds almost no
business logic of its own — it calls Foundation’s REST API (
/api/v1, session auth) and renders what comes back. Its API client is generated directly from Foundation’s OpenAPI schema, so the contract between them is the schema. - Foundation is the system of record. It owns the database (PostgreSQL), runs the asynchronous work over NATS JetStream (OCR, classification, response generation, payment refreshes), indexes for search in Typesense, and stores documents in S3/MinIO.
- Foundation → Forth is one-directional. Foundation pulls from Forth and maps legacy records into its own models. Forth is not being written back to as a primary store — it’s the source we’re draining. See Where We’re Headed.
- External services hang off Foundation, not Resonance — payments (Unity FI, Cornerstone, VGS), communications (Postmark, Twilio, postal mail), and AI classification (Claude). The exceptions are the two things that are genuinely client-side concerns: error tracking (Sentry) and onboarding-call booking (Calendly). Full list in Integrations.
Why it’s split this way
Section titled “Why it’s split this way”Keeping Foundation as the single system of record — and Resonance as a schema-driven client — means there’s one place the truth lives and one contract between the two. That’s also what makes the Forth exit tractable: consumers of the data talk to Foundation, so Forth can be drained behind that boundary without every client needing to know.
Source: resonance/docs/PROJECT_OVERVIEW.md, resonance/openapi-ts.config.ts,
foundation/config/settings.py, foundation/docs/NATS-PIPELINES.md.