Skip to main content
We welcome contributions to AppFlowy Editor! This guide will help you get started with contributing to the project.

Getting Started

Prerequisites

Before contributing, ensure you have:
  • Flutter SDK (latest stable version)
  • Git installed and configured
  • A GitHub account
  • Basic understanding of Dart and Flutter
  • Familiarity with the editor architecture

Setting Up Your Development Environment

  1. Fork the repository on GitHub
  2. Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/appflowy-editor.git
cd appflowy-editor
  1. Add upstream remote:
git remote add upstream https://github.com/AppFlowy-IO/appflowy-editor.git
  1. Install dependencies:
flutter pub get
  1. Run tests to ensure everything works:
flutter test

Types of Contributions

We appreciate various types of contributions:
Found a bug? We’d love your help fixing it!
  1. Check if an issue already exists
  2. Create a new issue if needed, describing the bug
  3. Reference the issue in your pull request
  4. Include tests that reproduce and fix the bug
Have an idea for a new feature?
  1. Open an issue to discuss the feature first
  2. Wait for maintainer feedback before implementing
  3. Keep the scope focused and manageable
  4. Include documentation and tests
  5. Update the CHANGELOG.md
Documentation improvements are always welcome!
  • Fix typos or unclear explanations
  • Add code examples
  • Improve API documentation
  • Create tutorials or guides
  • Translate documentation
Help improve test coverage:
  • Write unit tests for existing code
  • Add integration tests
  • Create widget tests
  • Improve test organization
Make the codebase better:
  • Improve code organization
  • Remove code duplication
  • Enhance performance
  • Update deprecated APIs

Development Workflow

1. Create a Branch

Create a descriptive branch for your work:
git checkout -b feature/your-feature-name
# or
git checkout -b fix/bug-description

2. Make Your Changes

Follow these guidelines while coding:
  • Write clean, readable code
  • Follow Dart style guidelines
  • Add comments for complex logic
  • Keep commits focused and atomic
  • Write descriptive commit messages

3. Test Your Changes

Ensure all tests pass:
# Run all tests
flutter test

# Run specific test file
flutter test test/path/to/test_file.dart

# Run tests with coverage
flutter test --coverage

4. Commit Your Changes

Write clear commit messages:
git add .
git commit -m "feat: add new block component for tables"
Commit message format:
  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • test: Test additions or changes
  • refactor: Code refactoring
  • chore: Maintenance tasks
  • perf: Performance improvements

5. Keep Your Branch Updated

Regularly sync with the upstream repository:
git fetch upstream
git rebase upstream/main

6. Submit a Pull Request

  1. Push your branch to your fork:
git push origin feature/your-feature-name
  1. Open a pull request on GitHub
  2. Fill out the pull request template
  3. Link related issues
  4. Wait for review

Code Style Guidelines

Dart Style

Follow the official Dart style guide:
# Format your code
dart format .

# Analyze for issues
flutter analyze

Naming Conventions

  • Classes: PascalCase (e.g., EditorState, BlockComponent)
  • Variables/Functions: camelCase (e.g., editorState, updateSelection)
  • Constants: lowerCamelCase (e.g., defaultEditorStyle)
  • Private members: Prefix with _ (e.g., _privateMethod)

Code Organization

// 1. Imports (organized)
import 'dart:async';

import 'package:flutter/material.dart';

import 'package:appflowy_editor/appflowy_editor.dart';

// 2. Class declaration
class MyWidget extends StatefulWidget {
  // 3. Constructor
  const MyWidget({
    super.key,
    required this.editorState,
  });

  // 4. Public fields
  final EditorState editorState;

  // 5. Override methods
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  // 6. Private fields
  late final EditorScrollController _scrollController;

  // 7. Lifecycle methods
  @override
  void initState() {
    super.initState();
    _scrollController = EditorScrollController(
      editorState: widget.editorState,
    );
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  // 8. Build method
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  // 9. Private helper methods
  void _helperMethod() {
    // Implementation
  }
}

Testing Guidelines

Writing Tests

Every contribution should include appropriate tests:
import 'package:flutter_test/flutter_test.dart';
import 'package:appflowy_editor/appflowy_editor.dart';

void main() {
  group('Feature description', () {
    test('should behave as expected', () {
      // Arrange
      final editorState = EditorState.blank();
      
      // Act
      // Perform action
      
      // Assert
      expect(editorState.document.root.children.length, equals(1));
    });

    testWidgets('widget should render correctly', (tester) async {
      // Arrange
      await tester.pumpWidget(
        MaterialApp(
          home: AppFlowyEditor(
            editorState: EditorState.blank(),
          ),
        ),
      );

      // Act
      await tester.pump();

      // Assert
      expect(find.byType(AppFlowyEditor), findsOneWidget);
    });
  });
}

Test Coverage

Aim for high test coverage:
  • Unit tests: For business logic and utilities
  • Widget tests: For UI components
  • Integration tests: For complex workflows

Documentation Guidelines

Code Documentation

Document public APIs thoroughly:
/// Updates the editor selection to the specified [selection].
///
/// If [selection] is null, the current selection will be cleared.
/// If [reason] is provided, it will be used to identify the source
/// of the selection change for debugging purposes.
///
/// Example:
/// ```dart
/// editorState.updateSelection(
///   Selection.single(
///     path: [0],
///     startOffset: 0,
///     endOffset: 5,
///   ),
/// );
/// ```
void updateSelection(Selection? selection, {String? reason}) {
  // Implementation
}

README and Guides

When adding features, update relevant documentation:
  • Add examples to the example app
  • Update README.md if needed
  • Create or update guides
  • Add migration notes for breaking changes

Pull Request Guidelines

PR Title Format

Use conventional commit format:
  • feat: add table support
  • fix: cursor position after deletion
  • docs: update installation guide
  • test: add tests for selection service

PR Description Template

## Description
[Describe your changes in detail]

## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Testing
- [ ] Tests pass locally
- [ ] Added new tests
- [ ] Manual testing completed

## Checklist
- [ ] Code follows style guidelines
- [ ] Self-reviewed the code
- [ ] Commented complex sections
- [ ] Updated documentation
- [ ] No new warnings generated
- [ ] Added tests that prove the fix/feature works

## Related Issues
Closes #[issue number]

## Screenshots (if applicable)
[Add screenshots or GIFs]

Review Process

  1. Automated checks run on your PR
  2. Maintainer review - be responsive to feedback
  3. Address comments by making requested changes
  4. Final approval and merge by maintainers
Be patient! Maintainers are often busy. If you haven’t heard back in a week, it’s okay to politely ping.

Common Contribution Scenarios

  1. Fork and clone the repository
  2. Make the fix in the relevant file
  3. Commit with message: docs: fix typo in [file/section]
  4. Push and open a PR
No issue required for simple typo fixes.
  1. Comment on the feature request issue
  2. Wait for maintainer go-ahead
  3. Create a branch: feature/issue-number-description
  4. Implement the feature with tests
  5. Update CHANGELOG.md
  6. Submit PR referencing the issue
  1. Open an issue describing the feature
  2. Include use cases and examples
  3. Discuss with maintainers
  4. Once approved, implement following the workflow
  5. Be prepared to iterate based on feedback
  1. Open an issue describing the bug
  2. Include reproduction steps
  3. Create a branch with the fix
  4. Add a test that would have caught the bug
  5. Submit PR referencing the issue

Getting Help

Need help contributing?
  • Discord: Join the AppFlowy Discord community
  • GitHub Discussions: Ask questions or start discussions
  • Issues: Comment on related issues for guidance
  • Documentation: Check existing docs first

Recognition

Contributors are recognized in:
  • The CHANGELOG.md for each release
  • GitHub contributors list
  • Release notes
  • Project README (for significant contributions)

Code of Conduct

Be respectful and constructive:
  • Use welcoming and inclusive language
  • Respect differing viewpoints and experiences
  • Accept constructive criticism gracefully
  • Focus on what’s best for the community
  • Show empathy towards other community members
Harassment, trolling, or any form of discriminatory behavior will not be tolerated.

License

By contributing to AppFlowy Editor, you agree that your contributions will be licensed under the same license as the project (Apache License 2.0).

Next Steps

View Examples

Study existing code and patterns

Check Issues

Find issues to work on

Read Changelog

See what’s been changed recently

API Reference

Understand the codebase

Thank You!

Thank you for contributing to AppFlowy Editor! Your efforts help make the editor better for everyone.

Build docs developers (and LLMs) love