twentyhq/twenty
Building a modern alternative to Salesforce, powered by the community.
Full-stack open-source CRM platform with React frontend, GraphQL API, and multi-tenant backend architecture
User interactions in the frontend trigger GraphQL queries via Apollo Client to the NestJS backend, which dynamically generates schemas from workspace metadata and executes operations against tenant-isolated databases. The backend can trigger email notifications through the email service and external automations via Zapier integrations. Configuration flows from environment variables and runtime detection in the frontend, while the UI component system provides consistent theming and accessibility.
Under the hood, the system uses 3 feedback loops, 3 data pools, 3 control points to manage its runtime behavior.
A 8-component fullstack. 16512 files analyzed. Data flows through 6 distinct pipeline stages.
How Data Flows Through the System
User interactions in the frontend trigger GraphQL queries via Apollo Client to the NestJS backend, which dynamically generates schemas from workspace metadata and executes operations against tenant-isolated databases. The backend can trigger email notifications through the email service and external automations via Zapier integrations. Configuration flows from environment variables and runtime detection in the frontend, while the UI component system provides consistent theming and accessibility.
- Frontend Initialization — The React app loads from index.tsx, initializes Apollo Client with the server URL from ConfigLoader, and establishes GraphQL communication channel with authentication context
- Schema Generation — WorkspaceSchemaBuilder reads workspace metadata from the database and dynamically creates GraphQL schemas with custom object types, field resolvers, and permission rules specific to each tenant [WorkspaceMetadata → GraphQLResponse]
- Object Operations — Frontend components execute GraphQL queries and mutations for CRM operations (creating contacts, updating deals, managing pipelines) which the backend processes through dynamically generated resolvers [GraphQLResponse → WorkspaceMetadata]
- Email Rendering — EmailRenderer transforms TipTap JSONContent templates with dynamic data into HTML emails for password resets, workspace invitations, and notification workflows [EmailTemplate → EmailTemplate]
- External Integration — ZapierApp exposes Twenty operations as Zapier triggers and actions, allowing users to create automated workflows between Twenty and 3000+ external applications [ZapierIntegration → ZapierIntegration]
- UI Rendering — React components consume Apollo Client data and render using the twenty-ui component library with accessibility support from VisibilityHidden and related utilities [UIComponent]
Data Models
The data structures that flow between stages — the contracts that hold the system together.
packages/twenty-serverMulti-tenant workspace configuration with dynamic object schemas, field definitions, permission settings, and custom business logic rules
Created during workspace setup, continuously modified through the metadata API as users customize objects and fields, cached for runtime schema generation
packages/twenty-front/src/config/index.tsApollo Client response objects with data, loading states, error information, and network status for all frontend-backend communication
Generated by Apollo Client from GraphQL queries, cached in Apollo cache, transformed into component props and Jotai atoms for reactive updates
packages/twenty-emails/src/index.tsTipTap JSONContent structure with rich text nodes, attributes, and marks for composing transactional email content
Defined as static templates, rendered with dynamic data to HTML, sent via email service providers
packages/twenty-zapier/src/index.tsZapier platform configuration with version, authentication schema, trigger definitions, and action handlers for third-party automation
Configured once per integration, executed dynamically when Zapier workflows trigger, maintains authentication tokens and rate limits
packages/twenty-ui/src/accessibility/index.tsReact component props with accessibility attributes, theme tokens, and styling configurations following the design system
Instantiated during React rendering, styled with design tokens, managed through React lifecycle hooks and state
Hidden Assumptions
Things this code relies on but never validates. These are the things that cause silent failures when the system changes.
Assumes localhost development runs backend on port 3000 specifically, and production serves frontend and backend on the same port/protocol as the browser location
If this fails: If backend runs on different port in development or uses different protocol/port in production, GraphQL requests will fail with connection errors and the app won't load
packages/twenty-front/src/config/index.ts:getDefaultUrl
Assumes JWT tokens always have exactly 3 dot-separated parts and the payload is at index 1, encoded in base64url format
If this fails: If JWT format changes or malformed tokens exist, Buffer.from() will throw exceptions causing authentication to crash during testing
packages/twenty-e2e-testing/lib/utils/getAccessAuthToken.ts:decodePayload
Assumes DOM element with id 'root' exists in the HTML document, falling back to document.body if not found
If this fails: If neither root element nor document.body are available during SSR or in unusual environments, React rendering will fail silently or crash
packages/twenty-front/src/index.tsx:ReactDOM.createRoot
Assumes tokenPair cookie value contains a JSON object with accessOrWorkspaceAgnosticToken.token property structure
If this fails: If cookie structure changes or becomes corrupted, JSON.parse() or property access will throw errors, breaking authentication flow in tests
packages/twenty-e2e-testing/lib/utils/getAccessAuthToken.ts:decodeToken
Assumes window._env_ global variable or process.env are available and properly populated in browser environment
If this fails: In strict CSP environments or unusual deployment contexts, these variables might be undefined, causing fallback to potentially incorrect URL detection
packages/twenty-front/src/config/index.ts:REACT_APP_SERVER_BASE_URL
Assumes githubStarsModel table contains at least one record when sorting by timestamp descending
If this fails: If table is empty, githubStars?.[0] will be undefined and numberOfStars will be undefined, potentially rendering empty star counts in header
packages/twenty-website/src/app/_components/ui/layout/header/index.tsx:findOne
Assumes localhost and 127.0.0.1 are the only development hostnames that need special port handling
If this fails: Custom development domains (like local.twenty.com) or Docker container names won't get port 3000 treatment, causing API connection failures
packages/twenty-front/src/config/index.ts:getDefaultUrl
Assumes JWT tokens in cookies haven't expired and payload.type === 'ACCESS' identifies the correct token
If this fails: Expired tokens or mismatched token types will cause authentication failures in tests without clear error messages about token validity
packages/twenty-e2e-testing/lib/utils/getAccessAuthToken.ts:getAccessAuthToken
Assumes zapier-platform-core module is available and exports a version property at runtime
If this fails: If Zapier platform dependencies are missing or incompatible, the integration will fail to load with module resolution errors
packages/twenty-zapier/src/index.ts:platformVersion
Assumes this file is always auto-generated and manual edits should never be made, but provides no enforcement mechanism
If this fails: Developers might manually edit this file not realizing it's auto-generated, causing their changes to be lost during the next generation cycle
packages/twenty-ui/src/accessibility/index.ts:auto-generated comment
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
Stores GraphQL query results and entity data for offline access and optimistic updates in the React frontend
Multi-tenant PostgreSQL database storing workspace metadata, custom objects, user data, and business records with tenant isolation
Exports React components with accessibility features and design system tokens for consistent UI rendering
Feedback Loops
- Dynamic Schema Update (self-correction, reinforcing) — Trigger: Metadata changes in workspace configuration. Action: WorkspaceSchemaBuilder regenerates GraphQL schema and updates resolvers. Exit: Schema validation completes successfully.
- Apollo Cache Invalidation (cache-invalidation, balancing) — Trigger: GraphQL mutations modify server data. Action: Apollo Client updates local cache and refetches related queries. Exit: Cache consistency achieved with server state.
- Email Template Rendering (recursive, balancing) — Trigger: TipTap JSONContent processing with nested nodes. Action: EmailRenderer recursively traverses and transforms content nodes. Exit: All nodes processed into final HTML output.
Delays
- Schema Generation (compilation, ~Variable based on workspace complexity) — Frontend waits for schema availability before executing custom object queries
- Apollo Client Initialization (warmup, ~2-3 seconds on first load) — Loading screens displayed while GraphQL client establishes connection and fetches initial data
- Email Template Processing (async-processing, ~100-500ms per email) — Email delivery queued while templates render with dynamic content
Control Points
- Server Base URL (env-var) — Controls: GraphQL endpoint for Apollo Client connection. Default: REACT_APP_SERVER_BASE_URL or auto-detected from hostname
- Workspace Layout Configuration (architecture-switch) — Controls: Monorepo package organization and build target configuration. Default: packages directory for both apps and libraries
- Zapier Platform Version (runtime-toggle) — Controls: Zapier integration API compatibility and feature availability. Default: Platform version from zapier-platform-core
Technology Stack
Frontend framework for building the main CRM user interface with component-based architecture
GraphQL client managing API communication, caching, and state synchronization between frontend and backend
Node.js framework powering the GraphQL API backend with dependency injection and modular architecture
API query language enabling dynamic schema generation and efficient data fetching for workspace customization
Primary development language providing type safety across the entire monorepo codebase
Monorepo build system managing package dependencies, caching, and development workflow across 19 packages
Rich text editor framework used in the email template system for creating structured content with JSONContent format
Integration platform enabling workflow automation between Twenty and thousands of external applications
Key Components
- App (orchestrator) — Main React application component that initializes Apollo Client, routing, authentication context, and theme providers for the entire frontend
packages/twenty-front/src/index.tsx - WorkspaceSchemaBuilder (factory) — Dynamically generates GraphQL schemas based on workspace metadata, creating types, queries, mutations, and resolvers for custom objects and fields
packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/graphql-types/enum/index.ts - EmailRenderer (transformer) — Converts TipTap JSONContent email templates into HTML with dynamic data injection for transactional email delivery
packages/twenty-emails/src/index.ts - ZapierApp (adapter) — Zapier platform integration that exposes Twenty CRM operations as triggers and actions, handling authentication and data transformation
packages/twenty-zapier/src/index.ts - AccessibilityComponents (factory) — Provides screen reader and keyboard navigation support components ensuring WCAG compliance across the UI component library
packages/twenty-ui/src/accessibility/index.ts - ConfigLoader (resolver) — Determines server base URL from environment variables or runtime context, handling development vs production deployment scenarios
packages/twenty-front/src/config/index.ts - AuthTokenManager (adapter) — Extracts and decodes JWT access tokens from browser cookies for automated testing authentication flows
packages/twenty-e2e-testing/lib/utils/getAccessAuthToken.ts - GraphQLBackend (gateway) — Provides GraphQL endpoint URL configuration for end-to-end testing requests against the backend API
packages/twenty-e2e-testing/lib/requests/backend.ts
Package Structure
React-based web frontend providing the main CRM user interface with configurable views, forms, and workspace management
Node.js/NestJS GraphQL API backend handling multi-tenant workspaces, data modeling, authentication, and business logic
Email template system and renderer for transactional emails like password resets and workspace invitations
React component library providing reusable UI components and design system tokens used across the platform
Zapier integration adapter enabling workflow automation between Twenty and 3000+ external apps
Development utilities including Danger.js configurations for PR validation and contributor recognition
Shared constants, types, and utilities used across multiple packages
Marketing website built with Next.js showcasing product features and documentation
Playwright-based end-to-end testing suite for validating complete user workflows
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaRelated Fullstack Repositories
Frequently Asked Questions
What is twenty used for?
Full-stack open-source CRM platform with React frontend, GraphQL API, and multi-tenant backend architecture twentyhq/twenty is a 8-component fullstack written in TypeScript. Data flows through 6 distinct pipeline stages. The codebase contains 16512 files.
How is twenty architected?
twenty is organized into 4 architecture layers: Frontend Layer, API Layer, Integration Layer, Shared Libraries. Data flows through 6 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through twenty?
Data moves through 6 stages: Frontend Initialization → Schema Generation → Object Operations → Email Rendering → External Integration → .... User interactions in the frontend trigger GraphQL queries via Apollo Client to the NestJS backend, which dynamically generates schemas from workspace metadata and executes operations against tenant-isolated databases. The backend can trigger email notifications through the email service and external automations via Zapier integrations. Configuration flows from environment variables and runtime detection in the frontend, while the UI component system provides consistent theming and accessibility. This pipeline design reflects a complex multi-stage processing system.
What technologies does twenty use?
The core stack includes React (Frontend framework for building the main CRM user interface with component-based architecture), Apollo Client (GraphQL client managing API communication, caching, and state synchronization between frontend and backend), NestJS (Node.js framework powering the GraphQL API backend with dependency injection and modular architecture), GraphQL (API query language enabling dynamic schema generation and efficient data fetching for workspace customization), TypeScript (Primary development language providing type safety across the entire monorepo codebase), Nx (Monorepo build system managing package dependencies, caching, and development workflow across 19 packages), and 2 more. A focused set of dependencies that keeps the build manageable.
What system dynamics does twenty have?
twenty exhibits 3 data pools (Apollo Client Cache, Workspace Database), 3 feedback loops, 3 control points, 3 delays. The feedback loops handle self-correction and cache-invalidation. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does twenty use?
5 design patterns detected: Multi-Tenant Architecture, Metadata-Driven Development, Monorepo Package Isolation, Apollo Client State Management, Component Library Pattern.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.