Architecture
GTM Clarity is a multi-tenant B2B SaaS scoring platform built with domain-driven design principles. This page covers the system architecture, data flow, and key design decisions.
System Overview
Tech Stack
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | Next.js 16.1.6, React 19.2.3, Tailwind CSS 4, Recharts 3.7 | Server-rendered UI with App Router |
| API | tRPC 11.10 | Type-safe RPC between frontend and backend |
| Auth | Clerk 6.39 | Multi-tenant authentication and RBAC |
| Database | PostgreSQL (Neon) + Drizzle ORM 0.45.1 | Serverless PostgreSQL with type-safe ORM |
| Workflows | Temporal.io 1.15 | Durable workflow orchestration for syncs |
| CRM | JSForce 3.10 | Salesforce API integration |
| Validation | Zod 4.3 | Runtime type validation at boundaries |
| Testing | Vitest 4.0, Playwright 1.58 | Unit and end-to-end testing |
Domain-Driven Design
The codebase is organized into bounded contexts, each with clear responsibilities and minimal coupling:
Context Boundaries
| Context | Responsibility | Coupling Rules |
|---|---|---|
| Connectors | External data ingestion, normalization | Writes to DB via canonical schema only |
| Scoring | Pure-function score computation | No DB access, no side effects, no API calls |
| Buying Groups | Role detection, completeness, discovery | Pure functions; DB access only via server layer |
| Server | DB access, API routing, middleware | Gateway to all contexts |
The scoring engine is completely pure -- it takes data in and returns scores. It never touches the database, makes API calls, or has side effects. This makes it trivially testable and deterministic.
Multi-Tenancy Strategy
GTM Clarity uses row-level tenant isolation. Every table includes a tenant_id column, and every query must filter by it:
The tenantColumns helper from src/server/db/schema/base.ts ensures every table definition includes the tenant_id column:
export const tenantColumns = {
tenantId: text("tenant_id").notNull(),
};
Key invariants:
- No cross-tenant queries -- every SELECT, UPDATE, DELETE includes
tenant_id - Clerk organization = tenant -- the
clerk_org_idmaps to one tenant row - Indexes include tenant_id -- all composite indexes lead with
tenant_idfor query performance
Data Flow
Inbound (Connector Sync)
Outbound (Score Writeback)
Scores computed by the engine can be pushed back to the source CRM:
- Writeback workflow reads scored entities from the
engagementstable - Maps canonical score fields to CRM-specific fields via
writeback_configs - Updates CRM records via the connector's API (e.g., Salesforce custom fields)
Scoring Pipeline
Security Architecture
| Layer | Mechanism |
|---|---|
| Authentication | Clerk (session tokens, SSO) |
| Authorization | RBAC middleware (org:admin, org:manager, org:viewer) |
| Tenant isolation | Row-level filtering on tenant_id |
| Token storage | AES-256-GCM encryption at rest (CONNECTOR_ENCRYPTION_KEY) |
| Audit | Append-only audit_log for all mutations |
| Input validation | Zod schemas at all system boundaries |
| Server isolation | server-only imports prevent client bundling of secrets |
Directory Structure
src/
app/ # Next.js App Router (pages, layouts, API routes)
components/ # React UI components by domain
connectors/ # Connector framework + implementations
salesforce/ # Salesforce connector
temporal/ # Temporal workflow orchestration
buying-groups/ # Buying group intelligence (pure functions)
scoring/ # Pure-function scoring engine
fit/ # ICP match scoring
engagement/ # Behavioral engagement with decay
rollup/ # Account/opportunity aggregation
server/ # Backend infrastructure
db/ # Drizzle ORM + schema (17 tables)
trpc/ # tRPC routers + middleware
lib/ # Shared utilities
types/ # TypeScript type definitions
Related Pages
- Database Schema -- Full schema with ER diagram
- Scoring Configuration -- Configuring the scoring engine
- Temporal Workflows -- Workflow orchestration details
- Environment Setup -- Infrastructure prerequisites