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