Web application
apps/web · Next.js 15
Marketing site, authenticated workspace, demo experiences, and in-app help. Metadata-driven views with a configurable base path for reverse-proxy hosting.
Developer documentation
Product architecture, platform model, security, API integration, and extensibility for teams evaluating or building on Sparo — a metadata-driven, multi-tenant customer-operations platform.
Overview
Sparo is a metadata-driven customer-operations platform. CRM is the first application — pipeline, automation, marketing, reporting, and governed AI on a tenant-safe core.
Accounts, leads, opportunities, tasks, activities, kanban, and reporting — all tenant-validated.
Calls, meetings, and sent/received email on records for team-wide visibility.
Web forms, ingest API, segments, and nurture sequences.
Event and scheduled triggers with a condition DSL and execution feed.
Tool registry, conversation persistence, usage telemetry, demo rate limits, and scope guardrails.
Cookie sessions, CSRF, OIDC/SAML SSO, and external secret references (env://, aws-sm://).
Architecture
A Next.js web application and NestJS API share platform packages. Industry verticals extend metadata and demo tenants — they do not fork the core.
apps/web · Next.js 15
Marketing site, authenticated workspace, demo experiences, and in-app help. Metadata-driven views with a configurable base path for reverse-proxy hosting.
apps/api · NestJS
CRM, metadata, workflows, ingest, outbound channels, auth/SSO, and the AI agent pipeline. Every handler receives a tenant-scoped request context.
packages/metadata-engine · types
Default CRM schema, merge engine, and shared contracts consumed by web, API, and AI modules.
packages/*-domain
Industry-specific pipeline stages, custom fields, and schema overrides — merged onto the platform default without forking core code.
packages/database · Drizzle
PostgreSQL schema, migrations, and the development seed that provisions tenants, RBAC, and demo datasets.
Platform model
These constraints apply across CRM, workflows, ingest, and AI — regardless of industry vertical.
Security
Tenant isolation, role-based access, governed AI, and cryptographic controls are enforced at the API layer — not left to client-side convention.
Every API request is scoped to a tenant UUID. Row-level filters and RBAC permissions are enforced before any CRM data is read or written.
Live product demos are gated behind HMAC-signed links with a fixed expiry. Sessions use httpOnly cookies and auto-revoke — keys are never left in the URL after the first visit.
Auth sessions use signed JWTs with issuer, audience, and expiry checks. Public customer links (booking, estimates, feedback) use single-use HMAC tokens.
Agents propose changes; humans confirm before anything is persisted. AI answers for metrics are computed by deterministic SQL, not guessed by the model.
Production responses include HSTS, X-Content-Type-Options, frame controls, and a strict referrer policy on every page.
Record creates, updates, and deletes are attributed to the acting user or agent. Enterprise deployments can extend this to SSO/SAML identity assertions.
For a full trust overview including demo access controls and transport hardening, see the security page. Enterprise deployments support SSO/SAML and external secret references for provider keys.
API
CRM and AI routes require an authenticated session with tenant context. Public lead capture uses the canonical ingest endpoint with per-channel credentials.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/health | Liveness check. |
| GET | /api/auth/session | Resolve the active session and workspace memberships. |
| GET | /api/crm/leads | List leads (tenant-scoped, permission-gated). |
| POST | /api/ingest/:tenant/:channel | Canonical public lead capture. |
| POST | /api/ai/conversations/:id/turn | Agent turn — tool loop with persistence. |
| GET | /api/ai/demo-usage/status | Remaining demo AI quota for the active user. |
POST /api/ingest/{tenantSlug}/{channelSlug}
Content-Type: application/json
{
"fields": {
"firstName": "Dana",
"lastName": "Whitfield",
"email": "dana@acme.com",
"company": "Acme Lending"
},
"customAttributes": {
"capture_channel": "inbound_form",
"account_segment": "mortgage_lending"
}
}Inbound channels are provisioned per tenant with authentication and deduplication rules. Contact us for channel setup, SSO integration, and sandbox credentials.
Extensibility
Sparo ships one core platform with industry verticals layered on metadata — custom objects, pipeline stages, ingest channels, and demo tenants without forking CRM logic.
Domain package
Create packages/<vertical>-domain with pipeline stages, capture channels, custom fields, and a schema override merged via mergePlatformSchemas().
Demo package
Create packages/demo-<tenant> with slug, branding, assistant prompts, and storyboard content.
Seed block
Extend packages/database/src/scripts/seed-dev.ts — tenant row, RBAC tiers, metadata bundle, channels, and sample CRM data.
Web route
Add apps/web/src/app/demo/<tenant>/ with a layout gate and <TenantDemoExperience tenant={…} />.
Vertical packages in the monorepo (roofing, enterprise sales, medical devices) demonstrate the pattern. Partner and enterprise extensions follow the same metadata-merge model.
For evaluation support, integration planning, or a security review of your deployment, reach out to the team.