TwentyMobile is a native mobile application developed with Flutter that serves as a unified client for CRM backends, starting with an integration with Twenty CRM. The project's goal is to allow users to manage contacts, companies, notes, and tasks on the go, with a modern, fast, and responsive interface.
Official Website: twentymobilecrm.luciosoft.it
Project Namespace: com.luciosoft.pocketcrm
- Onboarding & Authentication: Connection to a self-hosted Twenty CRM instance via URL with two access modes: API Token (for administrators) or Email/Password (for standard users). Secure credential storage and integration with Sentry for error monitoring.
- Demo Mode: Full exploration of the interface and features through an isolated test environment with a security lock on mutations.
- Dashboard (Home): A quick overview to start the day, featuring dynamic greetings, upcoming tasks, today's tasks, and recently viewed contacts.
- Contact Management:
- Interactive contact list with quick search functionality.
- Comprehensive contact detail view.
- Rapid creation and editing of contacts with optimistic updates (Optimistic UI).
- Contact sharing and direct export to the system's address book (iOS/Android).
- iOS 18+ Contacts Provider: Settings toggle Show Twenty people in iOS Contacts adds a live Twenty account in the iOS Contacts app. People stay in a provider container (not copied to iCloud).
- Rapid capture via integrated Business Card Scanner.
- Quick actions for sending emails or starting phone calls.
- Company Management:
- Company list and dedicated detail page with linked contacts.
- Fast opening of company websites in the native browser.
- Advanced Notes:
- Chronological view of linked notes.
- Quick text note taking from details or home screen.
- Secure Voice Note recording, allowing you to dictate and save information hands-free.
- Task Management & Notifications:
- List of assigned tasks with dynamic filtering (To Do / Completed).
- Task Assignment: Support for assigning tasks to specific workspace members (automatic for email login, manual via dropdown for admins).
- Scheduling with due dates.
- Advanced notification system (local push notifications) to remind about upcoming or overdue tasks.
- Manual Workflows:
- Fast execution of manual workflows directly from Contact and Company detail views via a quick action (⚡ bolt icon) in the AppBar.
- Multi-step interactive flow (Bottom Sheet) including active workflow selection, real-time loading (shimmer effect), and empty state.
- Dynamic Input Forms: Automatically renders input fields based on workflow schema constraints, with support for types such as
TEXT,NUMBER,SELECT(dropdown), andBOOLEAN(switch). - Premium Slide-to-Execute confirmation button with anti-fat-finger threshold, linear haptic feedback progress, and shake feedback animation on errors.
- Dynamic & Custom Workspace Objects (More Section):
- Full support for standard or custom CRM objects (e.g. Opportunities, custom reports) defined dynamically on the Twenty CRM backend.
- Generates GraphQL queries and mutations on the fly using runtime metadata.
- Lists workspace objects, including pagination (infinite scroll), text search, and pull-to-refresh.
- Dynamic Detail View: Inspects record properties, orders them, and lets users toggle their visibility (preferences saved locally per-object type via Hive).
- Dynamic Form Engine: Creates, edits, and saves dynamic records. Provides specialized fields for complex types:
- Currency: Dual-input for numeric amount (automatically converting to/from micros) and currency code.
- Relations: Searchable lookup pickers for linked contacts and companies.
- Full Name, Emails, Phones, Links, Addresses: Multi-field composite inputs that structure data precisely as expected by the Twenty CRM schema.
- UI/UX & Localization:
- Multi-language support with translations available in English (US/UK), Italian, French, German, and Hindi.
- Users can switch languages directly from the Settings menu.
- Robust adaptive layouts for software keyboard handling (preventing unintended rebuilds and text selections).
- Automatic cache invalidation on user change to ensure the integrity of displayed data.
PocketCRM dynamically fetches metadata for all workspace objects via Twenty CRM's GraphQL API.
- Fields Visibility & Sorting: From any dynamic object's detail screen, press the ⚙/⚡ settings icon to toggle which fields are visible and customize their display order. These settings are persisted locally.
- Relations Editing Support:
- Fields pointing to a
Companyopen the Company Picker Bottom Sheet. - Fields pointing to a
Person/Contactopen the Contact Picker Bottom Sheet. ACTORfields (likecreatedBy,updatedBy) are strictly read-only and point to their respective creators without allowing direct editing, keeping the workspace secure.
- Fields pointing to a
- Complex/Composite Fields: Input formats for Address, Currency, and Phone numbers are automatically structured to match Twenty's native DB types.
On iOS 18 or later, open Settings → iOS Contacts and enable Show Twenty people in iOS Contacts. Twenty people then appear as a live container named Twenty in the system Contacts app. This is not a one-off vCard export and does not copy contacts into iCloud. Disable the toggle or log out to remove the container.
PocketCRM supports running Twenty CRM manual workflows directly from the contact or company detail views. To use this feature successfully, please review the requirements and limitations below:
- Email & Password Login Required: To execute workflows, you must log in using your admin Email and Password (which generates a JWT token).
- API Key Limitation: Using a Twenty API Key (even with full Admin permissions) will result in a
FORBIDDEN(403) resource error from the Twenty GraphQL endpoint when attempting to trigger a workflow. This is an upstream limitation of the Twenty API.
- Trigger Type: Only workflows with a Manual trigger type set to
ACTIVEwill be displayed. - Entity-Specific Filtering:
- Workflows configured for the
Companyentity (or withavailability.objectNameSingularset tocompany) will appear on the Company Details screen. - Workflows configured for the
Person/Peopleentity (or withavailability.objectNameSingularset toperson/contact) will appear on the Contact Details screen. - Workflows configured as
GLOBAL(no specific entity target) will be available on both detail screens.
- Workflows configured for the
- Non-Interactive Workflows Only: Workflows should be designed to execute fully automated backend actions (e.g., sending HTTP requests, updating database records, sending Slack notifications).
- Interactive Steps Do Not Work: Workflows that contain standard web-based Form / interactive steps (where Twenty expects a user to fill in text or press a button inside the Twenty web app during execution) will hang in the
runningstate indefinitely when triggered via the API. - PocketCRM Warning: PocketCRM automatically detects workflows containing web-based form steps and displays a warning badge:
⚠ Contains form step (may require web app).
The architecture follows Domain-Driven Design (DDD) principles combined with a Feature-First approach in the presentation layer. The app uses the Connector Pattern to abstract calls to the source CRM.
An abstract CRMRepository interface is implemented by TwentyConnector (acting as a Facade that delegates to specific domain repositories like TwentyContactRepository, TwentyCompanyRepository, etc.). This allows for future expansions to other CRMs without modifying business logic or the UI.
The structure inside lib/ is organized by feature:
lib/
├── core/ # Global DI (Riverpod), Router, Theme, StorageService, Auth, Localization
├── domain/ # Core data models (Contact, Company, Task...), Repository interfaces (`CRMRepository`)
├── data/ # Infrastructure and Implementation
│ ├── connectors/ # BaseGraphQLConnector, TwentyConnector (Facade), DynamicObjectConnector
│ ├── repositories/ # Domain-specific repositories (Contact, Company, Task, Note, Workflow)
│ └── graphql/ # Centralized GraphQL queries (crm_queries.dart, auth_mutations.dart)
├── presentation/ # UI Layer (Feature-First)
│ ├── onboarding/ # Initial setup and Demo access
│ ├── home/ # Dashboard
│ ├── contacts/ # Contact module
│ ├── contact_detail/ # Contact details, voice note player/recorder
│ ├── companies/ # Company module
│ ├── scan/ # Business card scanner
│ ├── notes/ # Text notes module
│ ├── tasks/ # Tasks module
│ ├── workflows/ # Manual Workflows module (lists, dynamic forms, slide-to-confirm)
│ └── dynamic_objects/ # Support for Custom/Dynamic Workspace objects (lists, preferences, detail, form engine)
│ shared/ # Aesthetic widgets and cross-feature components (e.g., Demo block, pickers)
- Framework: Flutter (Mobile, iOS/Android ready)
- State Management & DI: Riverpod (
flutter_riverpod,riverpod_annotation) - Multi-Path Routing: GoRouter
- API Integrations: GraphQL (
graphql_flutter) - Code Generation: Freezed & JSON Serializable
- Notifications:
flutter_local_notifications,timezone - Security & Storage: Flutter Secure Storage, Hive
To start the project locally:
- Ensure you have the Flutter SDK (3.10+) installed.
- Pull dependencies:
flutter pub get
- Regenerate the code for models and providers (Riverpod & Freezed):
dart run build_runner build --delete-conflicting-outputs
- Run unit and widget tests:
flutter test - Launch the app on a simulator or physical device:
flutter run
Store builds correspond to official Git tags (e.g. v1.0.15). The version and build number are defined in pubspec.yaml (version: X.Y.Z+BUILD).
Ensure release signing credentials are configured in android/key.properties, then generate the signed Android App Bundle:
flutter build appbundle --releaseThe output file is generated at:
build/app/outputs/bundle/release/app-release.aab
- Verify CocoaPods and native dependencies are up to date:
(Note: The minimum iOS deployment target is iOS 15.5).
cd ios && pod install && cd ..
- Build the signed iOS App Store archive and
.ipapackage:flutter build ipa --release
The output IPA is placed at:
build/ios/ipa/TwentyMobile.ipa
You can distribute the .ipa using Apple Transporter or via the CLI:
xcrun altool --upload-app --type ios -f build/ios/ipa/TwentyMobile.ipa --apiKey <KEY_ID> --apiIssuer <ISSUER_ID>For upcoming features, privacy controls, UI enhancements, and future plans, check out the ROADMAP.md.
TwentyMobile is an open-source project distributed under the AGPL-3.0 license.