Skip to main content
Condo is structured as a Yarn workspaces monorepo orchestrated by Turbo. It contains 30+ independent applications and a set of shared internal packages. Apps cannot import code from each other — shared logic lives exclusively in packages/.

Tech stack

KeystoneJS 5

Backend framework that generates a GraphQL API from schema definitions. Each domain model is defined as a Keystone list.

Next.js

React-based frontend framework used for all server-rendered and client-side pages inside each Keystone app.

Apollo GraphQL

Apollo Client on the frontend and Apollo Server (via Keystone) on the backend. All data flows through GraphQL.

PostgreSQL 16

Primary relational database. Each application has its own database. Migrations are managed by kmigrator, a Django-based tool.

Redis 6.2

Used for session storage, asynchronous task queuing (via Bull), and caching.

Bull

Redis-backed task queue for asynchronous background jobs: notifications, imports, exports, and other long-running operations.

Turbo

Monorepo build orchestration. Manages task pipelines, caching, and parallel execution across workspaces.

Docker

Containerization for both local development (databases) and production deployment (full application stack).

Jest

Test runner with Jasmine2. Supports schema integration tests (.test.js) and unit tests (.spec.ts).

Monorepo layout

condo/
├── apps/          # Independent application services
├── packages/      # Shared internal libraries
├── bin/           # Build and utility scripts
├── docs/          # Project-level documentation
├── turbo.json     # Turbo pipeline configuration
└── package.json   # Root workspace configuration

apps/

Each directory under apps/ is a standalone service with its own database, environment variables, and deployment unit. Applications cannot import from each other.
AppDescription
condoMain property management application (KeystoneJS + Next.js)
resident-appResident-facing mobile/web application
dev-portal-webDeveloper portal frontend
dev-portal-apiDeveloper portal API service
address-serviceAddress resolution and normalization service
billing-connectorBilling system integration
callcenterCall center service
pos-integrationPoint-of-sale integration
miniappMini-app hosting service
news-greenhouseNews distribution service
property-importerProperty data import service
ticket-importerTicket data import service
telephonyTelephony integration
insuranceInsurance integration
accruals-gatewayAccruals gateway service
announcementsAnnouncements service
The monorepo contains 30+ apps in total. The table above lists the most prominent ones.

packages/

Shared internal libraries that any app can depend on. All packages are published under the @open-condo/* scope.
PackageDescription
@open-condo/uiUI component kit — the recommended way to build all GUI elements
@open-condo/iconsIcon library used across all applications
@open-condo/keystoneKeystone utilities: schema helpers, logging, test utilities
@open-condo/bridgeCommunication bridge for mini-app ↔ host integration
@open-condo/webhooksReusable webhook functionality for any app
@open-condo/miniapp-utilsUtilities for building mini-applications
@open-condo/apolloApollo client configuration and utilities
@open-condo/billingShared billing utilities
@open-condo/configConfiguration and environment variable utilities
@open-condo/codegenGraphQL code generation tooling
@open-condo/localesInternationalization and locale data
@open-condo/messagingMessaging abstractions
@open-condo/featureflagsFeature flag utilities
@open-condo/nextNext.js configuration and shared page utilities
@open-condo/filesFile upload and storage utilities
@open-condo/migratorDatabase migration tooling

The main app: apps/condo

apps/condo is the core property management application. It uses a domain-driven design structure where all business logic is organized into domain directories.

Domain structure

apps/condo/domains/
├── ticket/        # Maintenance request ticketing
├── billing/       # Payment tracking and invoices
├── contact/       # Resident contact management
├── property/      # Property and unit registry
├── organization/  # Organization and employee management
├── user/          # User accounts and authentication
├── notification/  # Push and messaging notifications
├── news/          # News posts and distributions
├── miniapp/       # Mini-app registry and management
├── marketplace/   # Service provider marketplace
├── meter/         # Utility meter readings
├── resident/      # Resident-specific data
├── scope/         # Access scope management
├── settings/      # Application settings
├── onboarding/    # Onboarding flows
├── analytics/     # Analytics and reporting
├── banking/       # Banking integrations
├── subscription/  # Subscription management
├── document/      # Document management
├── acquiring/     # Payment acquiring integrations
├── ai/            # AI-assisted features
└── common/        # Shared components and utilities
Each domain follows a consistent internal layout:
<domain>/
├── constants/     # Shared constants (client + server)
├── gql/           # GraphQL queries and mutations
├── components/    # React components (client)
├── schema/        # KeystoneJS list definitions (server)
├── access/        # Keystone access control (server)
└── utils/
    ├── clientSchema/  # Client-side schema utilities
    └── serverSchema/  # Server-side schema utilities

How apps communicate

Apps in the monorepo are isolated services. They communicate at runtime through GraphQL APIs — each app exposes its own Keystone-generated GraphQL endpoint.
┌─────────────────────┐     GraphQL      ┌──────────────────────┐
│   apps/condo        │ ───────────────► │  apps/address-service│
│   (main app)        │                  │  apps/billing-connector│
└─────────────────────┘                  └──────────────────────┘


┌─────────────────────┐
│   PostgreSQL        │  (per-app database)
│   Redis             │  (sessions, queues, cache)
└─────────────────────┘
Because apps cannot share code directly, any logic needed by multiple apps must be extracted into a package under packages/ and published as an internal workspace dependency.

Turbo build pipeline

Turbo orchestrates the build pipeline defined in turbo.json. Tasks declare their dependencies using ^ notation — for example, build depends on ^build, which means all upstream workspace dependencies must be built first.
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**", "build/**"]
    }
  }
}
This is why running yarn workspace @app/condo build:deps before starting the app is required — it triggers Turbo to build all packages that @app/condo depends on, in topological order.

Database and migrations

Each app manages its own database schema. Migrations are created and applied using kmigrator, a wrapper around the Django migration system:
# Apply pending migrations
yarn workspace @app/condo migrate

# Create new migrations after schema changes
yarn workspace @app/condo makemigrations
The migration tool requires Python 3 with Django and psycopg2-binary installed.

Next steps

Quick Start

Set up your local development environment and run Condo for the first time.

Project structure

Deep dive into the domain-driven design structure inside apps/condo.

Mini-Apps

Learn how to build mini-applications that extend Condo using the Bridge API.

GraphQL API

Explore the GraphQL API exposed by each Keystone application.

Build docs developers (and LLMs) love