Architecture
The system map and an index into the deep design docs. For the canonical thesis
and rules see ../../CLAUDE.md; for what's actually shipped see
../../README.md and ../roadmap.md.
The thesis: composable, not custom
We are the dashboard that makes five SaaS tools feel like one for B2B commercial fit-out studios (office · F&B · retail · education). We orchestrate the primitives (CRM, e-sign, 3D canvas, accounting, PM) and only build the glue plus the few things no SaaS does well:
- Agentic document pipeline — drop a plan/quote/BOQ → extract → classify → reconcile → price → human review. →
../agentic-pipeline.md - Catalog taxonomy — the 6-axis spine (
trade · element · work_type · room · pricing_basis · unit) every line maps to. →../catalog-taxonomy.md - Pricing intelligence — every price we ever see lands in one
price_observationtable → cost suggestions, supplier comparison, vendor scorecards. The moat that compounds. →../pricing-intelligence.md - Supplier portal + RFQ — magic-link inbound quotes, side-by-side comparison, accept → auto-PO. →
../supplier-portal.md
Glue rule: a primitive (CRM, e-sign, accounting, 3D canvas) → orchestrate; something ID-firm-specific (sketch→BOM, project-aware margin, deal-reg splits) → build.
The data spine
BOQ doc (PDF/CSV) ─► extract + classify ─► QUOTE (Section→Group→Line) ─► send ─► SOW ─► milestones ─► invoices
│ (Gemini / keyword + human-verify, learned per tenant) │ │
▼ ├─► generate POs ─► GRN ─► bills ─► 3-way match
price_observation ◄── historical import / supplier bills ◄───────────┘ │
│ (cost track = the moat) ▼
└────────────► cost suggestions · supplier comparison · margin · PROJECT P&L (revenue vs cost)
Every quote is sell-side; margins become real as supplier costs arrive (historical import / vendor bills). Auto-classification compounds: each human verification is learned per workspace, so the review burden trends toward zero.
Domain model (the nouns)
| Area | Core tables |
|---|---|
| Sales | Project · Quote + QuoteLine (with section/group/line_status) · Sow + milestones · Invoice · VariationOrder |
| Catalog & pricing | MaterialCategory · Vendor · Sku (cost, aliases, attributes: reorder_point/qty, material_type) · PriceObservation |
| Procurement | PurchaseOrder + lines · GoodsReceipt · VendorBill · Rfq + supplier quotes/invites |
| Warehouse (carpentry) | StockLocation · StockEvent (append-only ledger) · StockLevel (derived) · WorkOrder + BOM |
| Design pipeline | Plan · Wall · Opening · Room · Surface · Fixture |
| Access & ops | Tenant · User · Member (roles) · Invite · IntegrationOutbox · approvals/drafts |
Tenancy: tenant_id row-scoping is the norm (repo-wide enforcement deferred until a
second paying customer). Stock levels mirror the price_observation pattern — store
the facts (events), compute the view (levels).
Carpentry ops (warehouse + intake)
Raw materials → WIP work-orders → finished goods, with a message-intake agent and a
draft-and-approve gate. Inbound shop-floor/customer messages (Chatwoot/WhatsApp/webform)
are classified → stock events / job updates / CRM notes, with external actions parked in
Approvals. → ../carpentry-ops.md
Integrations (orchestrated, not rebuilt)
| Layer | Tool | Doc |
|---|---|---|
| CRM + pipeline | Attio | ../integrations/attio.md |
| Accounting / GST | Xero (default), ERPNext (self-host alt) | ../integrations/xero.md · ../integrations/erpnext.md |
| E-sign | PandaDoc | ../integrations/pandadoc.md |
| Project ops | Notion / ClickUp | ../integrations/notion.md · ../integrations/clickup.md |
| Intake | Typeform | ../integrations/typeform.md |
| Comms | WhatsApp · Telegram · Postmark | ../integrations/whatsapp.md · ../integrations/telegram.md · ../integrations/postmark.md |
| 3D canvas | Floorplanner SDK | (embedded; scene stored on the plan) |
Webhooks are the spine — everything async, idempotent, replayable (see the Webhook
outbox screen and POST /webhooks/{provider}).
Stack & ops
- Backend: FastAPI + SQLAlchemy 2.0 + PostgreSQL 16 + Alembic; a worker for async jobs.
- Frontend: Jinja2 + vanilla-JS scaffold pages at
/ui/<name>; Pico CSS theming. - AI: Gemini (BOQ PDF transcription, VLM plan extraction); keyword classifiers with per-tenant learning.
- Auth: sessions, optional TOTP 2FA, OIDC SSO, magic links. →
../auth.md - Deploy: Docker compose on Hetzner; rsync + rebuild. →
../deploy.md - Notifications: →
../notifications.md
Reference corpus
Real-shaped, anonymised BOQs that the pipeline + taxonomy are validated against:
../reference-quotes/ — REF-A (HDB resale) · REF-B (F&B mall) ·
REF-C (F&B Suntec) · REF-D (HDB Mandé) · REF-E (education/office).