Core Architectural Components of the AppFlowy Project: A Deep Dive into the Flutter-Rust Stack

AppFlowy implements a modular, multi-language architecture that isolates the Flutter UI from a Rust-based core engine via an FFI bridge, using a plugin-based event dispatcher to coordinate domain-specific services for folders, documents, databases, and AI functionality.

The AppFlowy project (AppFlowy-IO/AppFlowy) is structured as a cross-platform workspace application built with a strict separation between presentation and business logic. Understanding the core architectural components reveals how the codebase maintains portability across desktop and mobile platforms while delivering real-time collaborative features.

Overview of the Multi-Layer Architecture

AppFlowy organizes its codebase into distinct layers that communicate through well-defined interfaces. The architecture separates platform-specific UI code from the business logic, enabling the core engine to run independently of the front-end implementation.

The stack consists of three primary layers: the Flutter front-end responsible for rendering, the Rust core engine handling business logic and state management, and the data persistence layer managing local storage and cloud synchronization.

The Flutter Front-End and FFI Bridge

Flutter UI Layer

The presentation layer resides in frontend/appflowy_flutter/ and contains all Dart code for widgets, screens, and user interaction logic. This is the only platform-specific component, handling platform channels and native UI rendering while delegating all data operations to the Rust core.

The FFI Bridge

Communication between Dart and Rust flows through the frontend/rust-lib/dart-ffi/ crate. This bridge marshals data between the two languages, exposing Rust APIs to Flutter and serializing requests into events that the core engine can process.

When a user creates a new document in the UI, the Flutter layer calls into the dart-ffi crate, which forwards the request to the Rust dispatcher for execution.

The Rust Core Engine

AppFlowyCore Entry Point

The central orchestration happens in frontend/rust-lib/flowy-core/src/lib.rs. The AppFlowyCore::new function initializes the entire system, creating the configuration, logger, and background task scheduler.

// flowy-core/src/lib.rs – AppFlowyCore::new
let core = AppFlowyCore::new(config, runtime, stream_log_sender).await;

This entry point loads all domain service managers and establishes the dependency resolution system that wires services together.

Event Dispatcher and Plugin System

The core uses an event-driven architecture to decouple UI calls from business logic implementation. The make_plugins function in frontend/rust-lib/flowy-core/src/module.rs registers all domain services with the AFPluginDispatcher.

// flowy-core/src/module.rs – make_plugins
pub fn make_plugins(
    folder_manager: Weak<FolderManager>,
    database_manager: Weak<DatabaseManager>,
    user_manager: Weak<UserManager>,
    document_manager: Weak<DocumentManager>,
    search_manager: Weak<SearchManager>,
    ai_manager: Weak<AIManager>,
    storage_manager: Weak<StorageManager>,
) -> Vec<Box<dyn AFPlugin>> {
    vec![
        Box::new(FolderPlugin::new(folder_manager)),
        Box::new(DatabasePlugin::new(database_manager)),
        // … other domain plugins …
    ]
}

Each plugin implements the AFPlugin trait and handles specific event types, allowing the system to route calls from the FFI bridge to the appropriate service handler.

Domain Services and Business Logic

AppFlowy encapsulates each major feature area in its own crate, following a consistent pattern of trait-based service definitions and dependency resolution.

Folder, Document, and Database Services

The primary domain crates include:

  • flowy-folder/: Manages workspace hierarchy and view structures
  • flowy-document-pub/: Handles rich-text document editing
  • flowy-database-pub/: Manages grid and board views

Each service implements specific traits (e.g., FolderService, DocumentService) defined in their respective *_pub crates. The FolderServiceImpl in frontend/rust-lib/flowy-folder-pub/src/query.rs demonstrates this pattern:

// flowy-folder-pub/src/query.rs
pub trait FolderService: FolderQueryService + FolderViewEdit {}

pub struct FolderServiceImpl {
    folder_manager: Weak<FolderManager>,
    user: Weak<AuthenticateUser>,
}
impl FolderService for FolderServiceImpl {}

AI and Search Services

Specialized services extend core functionality:

  • flowy-ai-pub/: Generates content suggestions and manages embeddings using a local vector database
  • flowy-search-pub/: Provides full-text indexing via Tantivy for fast document retrieval

User and Storage Services

  • flowy-user-pub/: Handles authentication and user preferences
  • flowy-storage-pub/: Manages file attachments and binary data storage

Each service uses a dependency resolver (e.g., FolderDepsResolver, DatabaseDepsResolver) to receive its required dependencies, including the shared AppFlowyCollabBuilder and ServerProvider.

Data Persistence and Collaboration

Collab Integration

Real-time collaborative editing relies on the collab-integrate/ and collab-* crates. The AppFlowyCollabBuilder constructs Collab instances that domain services use for CRDT-based conflict resolution.

All domain services share this collaboration layer, ensuring that changes to folders, documents, and databases merge correctly across concurrent edits.

Local Storage

When operating offline, AppFlowy persists data via flowy-sqlite/ and flowy-storage/. The KVStorePreferences and StorageManager handle local SQLite databases and file system storage, managed through the FileStorageResolver.

Cloud and Server Infrastructure

Server Layer

The frontend/rust-lib/flowy-server/src/ directory contains the ServerProvider, which abstracts the difference between local-only mode and cloud synchronization. This layer supplies the LoggedUser implementation for authentication and manages remote storage adapters.

Background Processing

Task Scheduler

Long-running operations execute through the TaskDispatcher and TaskRunner found in frontend/rust-lib/lib-infra/src/task.rs. Created during AppFlowyCore::init, this system manages periodic tasks like search indexing and cloud uploads without blocking the main thread.

How the Components Connect at Runtime

The startup sequence demonstrates how these architectural components integrate:

  1. Initialization: AppFlowyCore::new loads configuration and creates the task scheduler
  2. Dependency Resolution: Resolvers construct services with the AppFlowyCollabBuilder and ServerProvider
  3. Plugin Registration: make_plugins registers all services with the AFPluginDispatcher
  4. UI Integration: Flutter calls Rust through dart-ffi, which routes events to the appropriate plugin
  5. Data Flow: Services persist changes locally or sync to the cloud via the server layer

Summary

  • AppFlowy separates UI and logic using a Flutter front-end and Rust core engine connected via FFI
  • The event dispatcher and plugin system in flowy-core decouple UI calls from business logic
  • Domain services (folder, document, database, AI) live in separate crates with trait-based APIs
  • Collab integration provides real-time CRDT-based synchronization across all data types
  • The server layer abstracts cloud sync while local storage handles offline persistence
  • A background task scheduler manages indexing and uploads without blocking user interactions

Frequently Asked Questions

How does AppFlowy handle communication between Flutter and Rust?

AppFlowy uses an FFI bridge located in frontend/rust-lib/dart-ffi/ to marshal data between Dart and Rust. The bridge converts Flutter method calls into events that the Rust AFPluginDispatcher routes to the appropriate domain service, returning results back to the UI asynchronously.

What is the role of the AppFlowyCollabBuilder?

The AppFlowyCollabBuilder constructs Collab instances that power real-time collaborative editing across all domain services. Located in the core integration layer, it ensures that folder structures, documents, and database records use consistent CRDT-based conflict resolution when merging local and remote changes.

How are new features added to the AppFlowy architecture?

Developers create a new crate in frontend/rust-lib/ following the existing service pattern: define traits in a *-pub crate, implement the service with a manager struct, create a dependency resolver, and register a plugin in flowy-core/src/module.rs. The service then becomes available to the Flutter UI through the existing FFI bridge without modifying core infrastructure code.

Does AppFlowy support multiple front-ends beyond Flutter?

Yes. The architecture intentionally isolates all business logic in Rust with a clean trait-based API. While the current implementation uses Flutter for the UI, the core engine could theoretically support alternative front-ends (Tauri, web, or native mobile) by implementing a new FFI layer that calls the same Rust services.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →