Product
Technical Blueprint — SoConnective · CRM
Changelog
- 2026-06-13 — Pivot to multi-tier SaaS platform (Platform → Agencies → Sub-accounts) with an installable module marketplace and an AI onboarding concierge. Tenancy becomes hierarchical (tenant
type+parent), config is per account, agencies deploy modules to sub-accounts (hybrid creds, per-module override). See ADR 0008. Supersedes the flat single-tenant assumption.- 2026-06-12 — created (INIT, was Spanish), then rewritten in English and reconciled with the ADRs. This document is the technical source of truth; architectural decisions live in
docs/architecture/decisions/(ADRs) and are referenced here rather than duplicated.
1. Product
SoConnective is the self-hosted, AI-native operating system for Feedback Studios (a marketing agency): a team CRM at the core, plus a client portal, native conversations, native automation, and AI agents. Philosophy: efficient manual process first → automation → AI.
- Tenancy: multi-tenant agency → sub-accounts (clients). Isolation by
tenant(Payload multi-tenant plugin + forced Postgres RLS). See ADR 0003, 0004. - Business model: internal use first; later a self-hosted SaaS / white-label product. No feature-gating.
2. Stack
| Layer | Choice | Why |
|---|---|---|
| Frontend (CRM / portal / web) | Next.js 16 + React 19 + Tailwind v4 + shadcn (Shadcn UI Kit) | App Router, server actions, finished, branded admin template. ADR 0005 |
| Backend / engine / API / auth / CMS | Payload CMS 3 on Postgres, schemaName: 'payload' | MIT, self-host, REST+GraphQL, auth, collections, hooks, multi-tenant. ADR 0004 |
| Database | PostgreSQL + Drizzle (packages/db) with forced RLS + app_user NOSUPERUSER | Single source of truth, tenant isolation at the DB. ADR 0003. Prod schema by migrations (ADR 0007) |
| Auth | Payload JWT → httpOnly crm_token cookie (7d) → server-side Authorization: JWT | Robust sessions; route guard in proxy.ts |
| Automation | Native engine (hooks → actions), no n8n | Full control of the engine + identity graph. ADR 0006 |
| Conversations | Native omnichannel (no Chatwoot) | Control of the identity graph. ADR 0006 |
| AI | Claude (opus / sonnet) | Agents, drafting, summarisation, "ask your CRM" |
| Email (transactional) | TBD (Resend / Postmark / SES) | Verification, reset, notifications |
| Payments | Stripe (Phase 6) | Invoices, subscriptions, MRR |
| Hosting / CI | Coolify + Traefik + Forgejo on the Vidot VPS | Self-host, deploy on push |
3. Architecture
Components, environments and the request path are described in docs/architecture/overview.md. Environments: local (support/backup only) and prod (the Vidot VPS, deployed by Coolify from Forgejo). Domains: backend. (engine) · crm. · portal.* · cms.* · docs. · website (apex). (* = later phases.)
4. Data model
erDiagram
TENANT ||--o{ USER : memberships
TENANT ||--o{ COMPANY : scopes
TENANT ||--o{ CONTACT : scopes
TENANT ||--o{ DEAL : scopes
COMPANY ||--o{ CONTACT : has
CONTACT ||--o{ IDENTITY : channels
CONTACT ||--o{ DEAL : primary
DEAL }o--|| COMPANY : derived
DEAL }o--o{ SERVICE : serviceInterest
CONTACT ||--o{ ACTIVITY : timeline
DEAL ||--o{ ACTIVITY : timeline
CONTACT ||--o{ TASK : todos
DEAL ||--o{ TASK : todos
CONTACT ||--o{ APPOINTMENT : meetings
DEAL ||--o{ APPOINTMENT : meetings
AUTOMATION ||--o{ AUTOMATIONRUN : logs
Live, tenant-scoped collections (Payload, schema payload): tenants, users, companies, contacts, identities, deals, services, activities, tasks, appointments, automations, automation-runs. Decisions: tenant on every scoped collection · deal company derived from the primary contact (read-only) · UTC in DB, local in UI · schema changes via committed migrations (ADR 0007).
5. Contracts
API (Payload REST, base PAYLOAD_URL)
| Method | Path | Auth | Notes |
|---|---|---|---|
| POST | /api/users/login | — | → JWT |
| GET | /api/users/me | JWT | current user + tenants |
| GET/POST | /api/:collection | JWT | list / create (with tenant) |
| GET/PATCH/DELETE | /api/:collection/:id | JWT | read / update / delete |
| GET | /api/:collection?where[field][op]=…&depth=N&sort=… | JWT | filters / relations |
Events / hooks (Payload afterChange)
| Source | Event | Handler | Notes |
|---|---|---|---|
| Deals | create / stage change / Owner change | logDealActivity | writes timeline Activity (same req transaction) |
| Contacts | lifecycle change | logContactActivity | writes timeline Activity |
| Deals | created / stage_changed / won | automateDeal | fires automation engine |
| Contacts | created | automateContact | fires engine |
| Tasks | status → Done | automateTask | fires task.completed |
| Appointments | created | automateAppointment | fires appointment.scheduled |
Background jobs (future)
Scheduled nurture/reminders, MRR checks, docs-sync (prebuild). The native automation engine currently runs synchronously inside the originating transaction; time-based triggers and queued execution are a later increment.
6. Integrations
| Service | Purpose | Status |
|---|---|---|
| Email (Resend/Postmark) | verification, reset, notifications | TBD |
| WhatsApp / Instagram | omnichannel inbox | Phase 2 |
| Stripe | payments, subscriptions, MRR | Phase 6 |
| Claude API | native AI | active |