Skip to content
mango·agentby Mangosteen Studio
Architecture

Architecture

One backend you own, a tiny widget, and a PWA inbox. Every external service sits behind an adapter.

System map#

Click a component for its role and technology.

Stack#

LayerChoice
WidgetVanilla TypeScript, shadow DOM, Vite library build, lazy capture module (modern-screenshot)
APIFastAPI on Python 3.13 with uv, SQLAlchemy 2 async, Alembic migrations
DataPostgres 16 with pgvector: conversations, leads, knowledge and vectors in one database
RealtimeWebSocket gateway with Redis pub/sub and an SSE fallback
FilesAny S3-compatible bucket (RustFS locally), private, behind signed URLs
Inbox / adminNext.js 16 PWA, React 19, Tailwind v4, Firebase Auth and Cloud Messaging
LLMGemini Flash-Lite through a router with fallbacks; fake provider for tests

Adapters: swap any dependency#

LLM, storage, push, email and CRM each sit behind one interface with a real and a fake implementation. Swapping a provider is one adapter plus config, not a rewrite. The fakes make the whole system run offline for development and tests.

SeamTodayLater
LLMGemini API (gemini_api), fakeVertex AI as a second provider
PushFirebase Cloud Messaging; logged when not configuredSlack, email digests
CRMInternal leads + CSV, FakeCrm through the outboxTwenty CRM adapter
EmailResend when RESEND_API_KEY is set, otherwise loggedOrg-level SMTP / provider settings
StorageS3-compatible (RustFS locally)R2, S3, GCS interop

Data model#

Click a table to see its key fields.

Outbox for side effects#

Pushes, emails and CRM writes are rows in an outbox table, delivered by a worker with retries and recorded per target. A failing provider never blocks a chat, and failures show in admin.

Security and privacy#

  • Public project keys work only on allowlisted domains. Visitor tokens are HMAC-signed with a short lifetime.
  • identify() requires a server-side HMAC signature.
  • Role checks on every inbox and admin query. Sign-in is invite-only.
  • Rate limits per IP, per visitor and per project, plus message and upload size caps.
  • Email is never required. Screenshots are masked before upload and stored privately.
  • Retention per project: 90 days for anonymous chats and 12 months for leads by default.