eddyter_flutter 1.0.2
eddyter_flutter: ^1.0.2 copied to clipboard
Embed the Eddyter rich text editor in Flutter apps on Android and iOS through a WebView. Requires a licensed Eddyter API key.
eddyter_flutter #
The official Flutter widget for the Eddyter rich text editor.
The editor is a web editor (Lexical). This package does not reimplement it natively: it loads the published @eddyter/core build inside a WebView and bridges events and file exports to Flutter. Android and iOS are supported.

Resources #
- Docs — Full API reference and integration guides
- What is Eddyter? Why Developers Are Switching to This AI Editor (2026) — YouTube
- Integrate Eddyter in 30 Minutes Using AI Tools Cursor, Claude, Lovable — YouTube
Related packages #
- eddyter — React (original editor package)
- @eddyter/core — Framework-agnostic core
- @eddyter/react-native — React Native
- @eddyter/vue — Vue
- @eddyter/svelte — Svelte
- @eddyter/angular — Angular
- @eddyter/astro — Astro
- eddyter/laravel — Laravel (Composer)
- eddyter-mcp — MCP server for AI coding tools
Requirements #
- Flutter 3.44+ (Dart 3.12+)
- Android 5.0+ (API 21) / iOS 13+
- An Eddyter license key
Installation #
flutter pub add eddyter_flutter
or add it to your app's pubspec.yaml:
dependencies:
eddyter_flutter: ^1.0.2
Then run flutter pub get. On iOS, run cd ios && pod install if your build doesn't do it for you.
Quick Start #
1. Get your API key #
- Create an account at eddyter.com
- Navigate to License Keys in your dashboard
- Copy your API key
The license key is bound to your app's Android applicationId / iOS bundle id. The widget reads that id from the compiled app with package_info_plus and sends it as X-Eddyter-App-Id; you cannot set or override it.
On the first successful validation the key is locked to app://<id>. A second app with a different id gets LICENSE_IN_USE until you Unassign the key on the License Keys page. Debug and release builds of the same id share one binding.
2. Configure Android #
The plugin already declares the camera and legacy storage permissions it needs. Add the rest to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
And a package-visibility query (inside <manifest>) so the share sheet can open after an export:
<queries>
<intent>
<action android:name="android.intent.action.SEND"/>
<data android:mimeType="*/*"/>
</intent>
</queries>
- Speech-to-text needs
RECORD_AUDIOandMODIFY_AUDIO_SETTINGS. The widget asks for the runtime permission itself. - Image upload uses the camera or the system photo picker.
- Export to Downloads: Android 10+ saves through MediaStore and needs no permission. Android 9 and below use
WRITE_EXTERNAL_STORAGE(declared by the plugin) and prompt once.
3. Configure iOS #
Add these keys to ios/Runner/Info.plist. Missing camera / photo keys crash the app when the editor opens Take Photo:
<key>NSMicrophoneUsageDescription</key>
<string>The editor uses the microphone for speech-to-text.</string>
<key>NSCameraUsageDescription</key>
<string>The editor uses the camera to take photos for image upload.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>The editor uses the photo library to attach images.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>The editor may save photos you capture for image upload.</string>
The widget requests microphone access itself. If you also use permission_handler elsewhere in your app, add PERMISSION_MICROPHONE=1 and PERMISSION_CAMERA=1 to your Podfile GCC_PREPROCESSOR_DEFINITIONS (see that package's README).
4. Add the widget #
import 'package:eddyter_flutter/eddyter_flutter.dart';
class NoteEditorScreen extends StatefulWidget {
const NoteEditorScreen({super.key});
@override
State<NoteEditorScreen> createState() => _NoteEditorScreenState();
}
class _NoteEditorScreenState extends State<NoteEditorScreen> {
String _html = '<p>Hello from Flutter</p>';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Note')),
body: Eddyter(
apiKey: 'YOUR_API_KEY',
initialContent: _html,
showStatus: false,
onChange: (html) => _html = html,
onReady: () => debugPrint('Editor ready'),
onError: (error) => debugPrint('Eddyter: $error'),
onExportSuccess: (path) => debugPrint('Saved $path'),
),
);
}
}
Give the widget a bounded height, for example as a Scaffold body or wrapped in Expanded inside a Column.
Keep the API key out of source control, for example with --dart-define=API_KEY=... and const String.fromEnvironment('API_KEY').
API Reference #
Eddyter #
| Parameter | Type | Notes |
|---|---|---|
apiKey |
String |
Required. Your Eddyter license key. |
initialContent |
String |
HTML the editor starts with. Default <p>Start writing...</p>. |
showStatus |
bool |
Shows a loading / error strip at the bottom until the editor is ready. Default true. |
exportMode |
EddyterExportMode? |
share, save or both. Default: Android both, iOS share. |
exportFilePrefix |
String? |
Prefix for exported file names. |
sdkVersion |
String |
@eddyter/core version loaded from unpkg. Defaults to kDefaultEddyterSdkVersion, the version this release is tested with. |
sdkScriptUrl / sdkStyleUrl |
String? |
Load the editor JS / CSS from your own host instead of unpkg. |
Callbacks #
| Parameter | Signature |
|---|---|
onChange |
void Function(String html) |
onReady |
void Function() |
onAuthSuccess |
void Function() |
onAuthError |
void Function(String error) |
onExportSuccess |
void Function(String filePath). A content:// URI or Downloads path when saved on Android. |
onExportError |
void Function(String error). onError is also called. |
onError |
void Function(String error). Load, network, license and runtime errors. |
Exporting PDF and Word #
Browser downloads (<a download>) don't work inside a WebView. The widget catches PDF / DOCX exports from the toolbar, writes the file to the app's documents directory, saves it to the public Downloads folder on Android (MediaStore or DownloadManager), and opens the system share sheet. Use exportMode to change this.
Notes #
-
The device needs network access: the editor loads from unpkg on startup, and the license key is validated online.
-
Some Huawei devices render a blank WebView with Impeller. If you see this, disable Impeller inside
<application>in your app'sAndroidManifest.xml:<meta-data android:name="io.flutter.embedding.android.EnableImpeller" android:value="false" />
License #
Eddyter is proprietary software.
- Free for evaluation and non-commercial use
- Commercial use requires a paid license
- SaaS, redistribution, and competing products are prohibited without permission
For commercial licensing, visit eddyter.com.