Skip to main content
The AppFlowy Flutter frontend provides a rich, cross-platform user interface with native performance on desktop and mobile platforms.

Project Structure

The Flutter app is located in frontend/appflowy_flutter/ with the following structure:
appflowy_flutter/
├── lib/                    # Main application code
│   ├── core/              # Core utilities and configuration
│   ├── features/          # Feature modules
│   ├── plugins/           # Plugin system
│   ├── shared/            # Shared widgets and utilities
│   ├── startup/           # Application initialization
│   ├── user/              # User management
│   ├── workspace/         # Workspace management
│   ├── mobile/            # Mobile-specific code
│   └── main.dart          # Application entry point
├── packages/              # Local packages
│   └── appflowy_backend/  # FFI bindings to Rust
├── assets/                # Images, fonts, icons
├── integration_test/      # Integration tests
├── test/                  # Unit tests
└── pubspec.yaml           # Dependencies

Key Directories

/lib/core/

Core application infrastructure:
  • config: App configuration and environment variables
  • helpers: Utility functions and helpers
  • notification: Notification handling from Rust backend

/lib/features/

Feature-based modules organized by domain:

workspace

Workspace management, sidebar, and navigation

settings

User settings, preferences, and account management

view_management

View creation, deletion, and organization

shared_section

Shared workspaces and collaboration features

/lib/plugins/

The plugin system enables extensible document types:
PluginDescription
documentRich text editor with blocks and formatting
databaseGrid, board, calendar, and kanban views
ai_chatAI-powered chat interface
blankBlank page template
database_documentDatabase with embedded document
Each plugin implements the Plugin interface and registers itself with the plugin system.

/lib/shared/

Reusable components and utilities:
  • widgets: Common UI components (buttons, dialogs, inputs)
  • bloc: Shared BLoC state management classes
  • models: Shared data models
  • styles: Theme and styling constants

/lib/mobile/

Mobile-specific implementations:
  • application: Mobile app state management
  • presentation: Mobile-optimized screens and widgets

State Management

AppFlowy uses the BLoC (Business Logic Component) pattern for state management:
// Example BLoC structure
class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
  DocumentBloc({
    required this.documentId,
  }) : super(DocumentState.initial()) {
    on<DocumentEvent>(_onDocumentEvent);
  }
  
  Future<void> _onDocumentEvent(
    DocumentEvent event,
    Emitter<DocumentState> emit,
  ) async {
    // Handle events and emit states
  }
}

BLoC Pattern Benefits

Separation of Concerns

Business logic is separated from UI, making code more maintainable

Testability

BLoCs can be easily unit tested without UI dependencies

Reusability

Business logic can be shared across different widgets

Predictability

State changes follow a unidirectional data flow

FFI Integration

The Flutter app communicates with the Rust backend through FFI:

Package Structure

packages/appflowy_backend/
├── lib/
│   └── dispatch/          # Event dispatch to Rust
├── macos/                 # macOS native code
├── ios/                   # iOS native code
├── android/               # Android native code
├── linux/                 # Linux native code
└── windows/               # Windows native code

Event Dispatch

1

Create event request

final request = UserEventGetUserProfile();
2

Dispatch to Rust

final result = await UserEventGetUserProfile().send();
3

Handle response

result.fold(
  (userProfile) => print('Success: ${userProfile.name}'),
  (error) => print('Error: $error'),
);

Code Generation

Protobuf definitions are used to generate Dart classes:
# Generate Dart code from .proto files
flutter pub run build_runner build

Application Lifecycle

Initialization Flow

1

main.dart entry

Application starts in main.dart with runAppFlowy()
2

Startup initialization

The startup/ module initializes core services:
  • Rust backend initialization
  • Dependency injection setup
  • Theme and localization
3

Authentication check

Check if user is logged in and load workspace
4

Render UI

Display the main workspace or login screen

Main Entry Point

// lib/main.dart
import 'package:scaled_app/scaled_app.dart';
import 'startup/startup.dart';

Future<void> main() async {
  ScaledWidgetsFlutterBinding.ensureInitialized(
    scaleFactor: (_) => 1.0,
  );
  
  await runAppFlowy();
}

Dependency Injection

AppFlowy uses the GetIt service locator for dependency injection:
// Register services
getIt.registerLazySingleton<AuthService>(() => AuthService());

// Access services
final authService = getIt<AuthService>();

Platform-Specific Code

Desktop vs Mobile

AppFlowy provides different UI implementations for desktop and mobile:
if (PlatformExtension.isDesktop) {
  return DesktopHomeScreen();
}

Responsive Design

The app uses responsive layouts that adapt to screen size:
LayoutBuilder(
  builder: (context, constraints) {
    if (constraints.maxWidth > 800) {
      return DesktopLayout();
    } else {
      return MobileLayout();
    }
  },
)

Testing

Test Structure

test/
├── bloc/           # BLoC unit tests
├── widget/         # Widget tests
└── util/           # Utility tests

integration_test/
└── *.dart          # Integration tests

Running Tests

cd appflowy_flutter
flutter test

Dependencies

Key Flutter packages used in AppFlowy:
PackagePurpose
flutter_blocState management with BLoC pattern
get_itService locator for dependency injection
ffiForeign function interface to Rust
freezedCode generation for immutable classes
protobufProtocol buffer serialization
flutter_localizationsInternationalization support
providerSimple dependency injection
go_routerDeclarative routing
See pubspec.yaml for the complete list of dependencies and versions.

Development Workflow

1

Install dependencies

cd frontend/appflowy_flutter
flutter pub get
2

Generate code

flutter pub run build_runner build --delete-conflicting-outputs
3

Run the app

flutter run

Next Steps

Rust Backend

Learn about the Rust backend architecture

Building Desktop

Build AppFlowy for desktop platforms

Build docs developers (and LLMs) love