Skip to main content

Monorepo Overview

Condo is organized as a monorepo using Yarn workspaces and Turborepo for build orchestration. The top-level structure is:
condo/
├── apps/          # Independent application services
├── packages/      # Shared internal libraries
├── bin/           # CLI scripts (prepare, migrations, etc.)
├── docs/          # Project-level documentation
└── docker-compose.yml
Apps are fully isolated — they cannot import code from each other. All shared code must live in packages/.

Apps (/apps/*)

Each app is a standalone service with its own database, environment, and deployment lifecycle.
AppDescription
condoMain property management web app (KeystoneJS + Next.js)
resident-appResident-facing mobile/web application
billing-connectorBilling system integration service
callcenterCall center service
pos-integrationPoint-of-sale integration
dev-portal-webDeveloper portal for mini-app builders
There are 20+ additional specialized apps in the repository.

Packages (/packages/*)

Packages are internal libraries that any app can depend on.

@open-condo/ui

The official UI component library. Use this for all GUI elements instead of building custom components.

@open-condo/icons

Icon library for consistent iconography across apps.

@open-condo/keystone

Core Keystone.js utilities: schema helpers, logging, test utilities, and more.

@open-condo/webhooks

Webhook functionality that can be added to any app.

@open-condo/bridge

Bridge utilities for mini-app communication.

@open-condo/miniapp-utils

Shared utilities for building mini-apps on the Condo platform.

Domain-Driven Design in apps/condo

The main condo application uses Domain-Driven Design (DDD) to organise its logic. All business logic lives under apps/condo/domains/, split by domain:
apps/condo/domains/
├── ticket/
├── billing/
├── contact/
├── property/
├── marketplace/
├── miniapp/
├── news/
├── notification/
├── user/
├── organization/
└── common/          # Shared components and utilities across domains

Domain Folder Structure

Every domain follows a consistent layout:
<domain>/
├── access/            # Keystone.js access control rules (server)
├── constants/         # Shared constants (client + server)
├── components/        # React components (client)
├── hooks/             # React hooks (client)
├── gql/               # GraphQL queries and mutations (client + server)
├── schema/            # Keystone.js schema models — defines the GQL API (server)
└── utils/
    ├── clientSchema/  # Client-side domain utilities
    ├── serverSchema/  # Server-side domain utilities
    └── testSchema/    # Test helpers for schema tests

Key Domains

DomainResponsibility
ticketCore ticket lifecycle management
billingPayment tracking and invoice management
contactResident contact management
propertyBuilding and property data
marketplaceService marketplace for contractors
miniappExtension system for third-party mini-apps
newsNews and announcements for residents
notificationNotification delivery (push, email, SMS)
userAuthentication and user management
organizationProperty management company data
commonBase components, form layouts, shared constants

Other App Directories

apps/condo/
├── domains/       # Domain-driven business logic
├── pages/         # Next.js page components (client)
├── public/        # Static assets (images, icons)
├── schema/        # Root-level Keystone schema config
├── lang/          # i18n translation files
└── migrations/    # Database migration files

Adding External Packages

The monorepo maintains a single shared yarn.lock, so all apps use the same version of each dependency.
# Add a package shared across all apps (preferred for most dependencies)
yarn add <package> -W

# Add a package to a specific app only
yarn workspace @app/condo add <package>

# Upgrade packages interactively
yarn upgrade-interactive --latest
Always prefer yarn add -W for external dependencies to avoid version conflicts across apps.

Code Style

The project enforces consistent style via ESLint. Key rules:
RuleValue
Indentation4 spaces
QuotesSingle quotes (')
SemicolonsNever
Object spacingAlways: { foo }
Trailing commasAlways in multiline arrays/objects
Space before function parenAlways: function example () {}

Import Order

Imports must be grouped in this order, with a blank line between each group:
import fs from 'fs'                                    // 1. Node built-ins

import React from 'react'                              // 2. External packages

import { getById } from '@open-condo/keystone/schema'  // 3. @open-condo packages

import { MyComponent } from './components'             // 4. Internal / sibling

Restricted Imports

  • Use pdfmake instead of jspdf
  • Do not import from @open-keystone/fields* or @open-condo/keystone/fields
  • Use specific lodash sub-module imports: import get from 'lodash/get' (not import { get } from 'lodash')
Run yarn lint:code:fix to auto-fix most style issues.

Build docs developers (and LLMs) love