Skip to main content
AFFiNE is a complex monorepo with frontend, backend, and native components. This guide helps you understand how it all fits together.

Repository Structure

The repository is organized as a Yarn monorepo:
AFFiNE/
├── packages/          # Production code
│   ├── backend/      # Server-side code
│   ├── frontend/     # Client-side code
│   └── common/       # Shared libraries
├── blocksuite/       # Editor framework
├── tools/            # Development tools
├── tests/            # E2E and integration tests
├── docs/             # Documentation
└── scripts/          # Build and utility scripts

Architecture Overview

graph TB A[Web/Desktop/Mobile] —> B[Frontend Core] B —> C[BlockSuite Editor] B —> D[GraphQL Client] D —> E[Backend Server] E —> F[PostgreSQL + pgvector] E —> G[Redis] E —> H[Storage S3/FS] B —> I[Y.js CRDT] I —> J[IndexedDB] I —> E

Frontend Architecture

Package Structure

packages/frontend/
├── apps/
│   ├── web/              # Web application
│   ├── electron/         # Desktop app
│   ├── electron-renderer/
│   ├── mobile/           # Mobile (Capacitor)
│   ├── mobile-shared/
│   ├── ios/              # iOS project
│   └── android/          # Android project
├── core/                # Business logic
├── component/           # UI components
├── i18n/                # Internationalization
├── native/              # Native Node.js modules
├── electron-api/        # Electron IPC API
└── routes/              # Routing configuration

Core Technologies

  • React 19: UI framework
  • TypeScript: Type-safe development
  • Jotai: State management
  • Vite: Build tool
  • Vanilla Extract: Type-safe CSS

Application Flow

  1. Bootstrap (packages/frontend/core/src/bootstrap/)
    • Initialize environment
    • Set up error tracking (Sentry)
    • Load polyfills
    • Start the app
  2. Routing (packages/frontend/routes/)
    • React Router v6
    • Lazy-loaded routes
    • Protected routes
  3. State Management
    • Jotai atoms for global state
    • React Context for component state
    • Framework service for complex state
  4. Data Layer
    • GraphQL for server communication
    • Y.js CRDT for documents
    • IndexedDB for local storage

Backend Architecture

Package Structure

packages/backend/
├── server/
│   ├── src/
│   │   ├── base/           # Core framework
│   │   ├── core/           # Business modules
│   │   │   ├── auth/       # Authentication
│   │   │   ├── user/       # User management
│   │   │   ├── workspaces/ # Workspace logic
│   │   │   ├── doc/        # Document operations
│   │   │   ├── storage/    # Blob storage
│   │   │   └── sync/       # Real-time sync
│   │   └── plugins/        # Plugin modules
│   │       ├── copilot/    # AI features
│   │       ├── payment/    # Stripe integration
│   │       ├── oauth/      # OAuth providers
│   │       └── ...
└── native/             # Rust native modules

Core Technologies

  • NestJS: Backend framework
  • GraphQL: API layer (Apollo Server)
  • Prisma: Database ORM
  • PostgreSQL: Primary database (with pgvector)
  • Redis: Caching and queues
  • Socket.io: WebSocket for real-time sync
  • BullMQ: Background jobs

Request Flow

  1. HTTP Request → Express middleware
  2. Authentication → Session/JWT validation
  3. GraphQL → Resolver execution
  4. Authorization → Permission checks
  5. Business Logic → Service layer
  6. Database → Prisma ORM
  7. Response → GraphQL formatter

BlockSuite Editor

BlockSuite is the editor framework powering AFFiNE:
blocksuite/
├── affine/              # AFFiNE-specific blocks
│   ├── model/           # Data models
│   ├── blocks/          # Block implementations
│   ├── shared/          # Shared utilities
│   └── widgets/         # UI widgets
├── framework/           # Core framework
│   ├── store/           # Document store
│   ├── global/          # Global state
│   └── std/             # Standard library
└── playground/          # Development playground

Key Concepts

  • Block: Smallest content unit (paragraph, image, etc.)
  • Page: Collection of blocks
  • Store: Y.js document store
  • Extension: Plugin for blocks/UI/functionality

Common Packages

Shared code between frontend and backend:
packages/common/
├── infra/               # Framework infrastructure
├── nbstore/             # Storage abstraction
├── graphql/             # GraphQL types
├── env/                 # Environment config
├── error/               # Error handling
├── theme/               # Theme system
├── s3-compat/           # S3-compatible storage
└── y-octo/              # Y.js CRDT (Rust)

Data Flow

Document Editing Flow

Authentication Flow

Storage Architecture

Client-Side Storage

  1. IndexedDB: Document data (Y.js updates)
  2. LocalStorage: User preferences
  3. CacheStorage: App assets (Service Worker)

Server-Side Storage

  1. PostgreSQL: Metadata, users, permissions
  2. Redis: Sessions, cache, job queues
  3. S3/Filesystem: Blob storage (images, files)

Real-Time Sync

WebSocket Protocol

AFFiNE uses Socket.io for real-time sync:
// Client connects
socket.emit('space:join', { spaceId, spaceType })

// Push updates
socket.emit('push-doc-update', { docId, update })

// Receive updates
socket.on('server-update-doc', ({ docId, update }) => {
  // Apply update to local document
})

// Awareness (presence)
socket.emit('awareness', { docId, awareness })

CRDT Conflict Resolution

Y.js CRDT automatically merges concurrent edits:
  • No locking required
  • Eventually consistent
  • Deterministic merge
  • Offline-capable

Build System

Development

# Start all services
yarn dev

# Start specific app
yarn workspace @affine/web dev

Production Build

# Build all packages
yarn build

# Build specific package
yarn workspace @affine/web build

Electron Build

# Package desktop app
yarn workspace @affine/electron package

# Create installers
yarn workspace @affine/electron make

Testing Architecture

tests/
├── affine-local/        # Local-first E2E tests
├── affine-cloud/        # Cloud E2E tests
├── affine-migration/    # Migration tests
└── fixtures/            # Test fixtures

Test Types

  • Unit Tests: Vitest
  • E2E Tests: Playwright
  • Integration Tests: Ava (backend)
  • Component Tests: React Testing Library

Deployment

Web Deployment

  1. Build static assets
  2. Upload to CDN/static hosting
  3. Configure reverse proxy (Nginx/Caddy)
  4. Set up SSL/TLS

Desktop Distribution

  1. Build native app
  2. Code sign (macOS/Windows)
  3. Notarize (macOS)
  4. Upload to release servers
  5. Auto-update via electron-updater

Self-Hosted

  1. Pull Docker image
  2. Configure environment
  3. Run with Docker Compose
  4. Set up reverse proxy
  5. Configure SSL

Development Setup

Set up your local environment

Testing Guide

Write and run tests

Coding Guidelines

Follow our coding standards

BlockSuite Docs

Learn about the editor framework

Build docs developers (and LLMs) love