Flutter SDK
Integrate Klero feedback, roadmap, changelog, surveys, and widgets into your Flutter app.
In-App Widget - Work in Progress
The In-App Widget (KleroWidget) is currently not working properly in Flutter due to platform limitations with WebView touch passthrough and overlay rendering. This is a known issue and we are actively working on a fix. All other modules (feedback, roadmap, changelog, surveys) work as expected.
Requirements
- Flutter >= 3.10.0
- Dart >= 3.0.0
Installation
flutter pub add klero_flutterQuick Start
Any Module with KleroEmbed
KleroEmbed is the generic widget that supports all Klero module types. Convenience widgets are also provided.
import 'package:klero_flutter/klero_flutter.dart';
// Using the generic widget
KleroEmbed(
projectSlug: 'myproject',
embedType: KleroEmbedType.feedback,
)
// Or use convenience widgets
KleroFeedback(projectSlug: 'myproject')
KleroRoadmap(projectSlug: 'myproject')
KleroChangelog(projectSlug: 'myproject')Full Page Example
import 'package:flutter/material.dart';
import 'package:klero_flutter/klero_flutter.dart';
class FeedbackPage extends StatelessWidget {
const FeedbackPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Feedback')),
body: const KleroFeedback(projectSlug: 'myproject'),
);
}
}Survey with KleroSurvey
For surveys, use the dedicated KleroSurvey widget which provides survey-specific event callbacks:
import 'package:klero_flutter/klero_flutter.dart';
KleroSurvey(
projectSlug: 'myproject',
surveyUlid: '01ABC123...',
onComplete: (data) {
print('Completed: ${data.responseUlid}');
print('Answers: ${data.answers}');
},
onClose: (data) {
print('Closed, completed: ${data.completed}');
},
onError: (error) {
print('Error: $error');
},
)Programmatic Control
KleroEmbed
import 'package:flutter/material.dart';
import 'package:klero_flutter/klero_flutter.dart';
class FeedbackPage extends StatefulWidget {
const FeedbackPage({super.key});
@override
State<FeedbackPage> createState() => _FeedbackPageState();
}
class _FeedbackPageState extends State<FeedbackPage> {
final _embedController = KleroEmbedController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Feedback'),
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () => _embedController.reload(),
),
],
),
body: KleroEmbed(
controller: _embedController,
projectSlug: 'myproject',
embedType: KleroEmbedType.feedback,
),
);
}
@override
void dispose() {
_embedController.dispose();
super.dispose();
}
}KleroSurvey
final _surveyController = KleroSurveyController();
// Open the survey
_surveyController.open();
// Close the survey
_surveyController.close();
KleroSurvey(
controller: _surveyController,
projectSlug: 'myproject',
surveyUlid: '01ABC123...',
)Authentication
Pass a customer token to identify logged-in users:
KleroFeedback(
projectSlug: 'myproject',
customerToken: 'your-jwt-token',
)See the Authentication Guide for token generation.
Custom Base URL
For self-hosted or custom domain setups:
KleroFeedback(
projectSlug: 'myproject',
baseUrl: 'https://feedback.mycompany.com',
)Additional Embed Config
Pass extra configuration to the embed:
KleroEmbed(
projectSlug: 'myproject',
embedType: KleroEmbedType.survey,
embedConfig: {'surveyUlid': '01ABC123...'},
)API Reference
KleroEmbed Properties
| Property | Type | Required | Description |
|---|---|---|---|
projectSlug | String | Yes | Your Klero project slug |
embedType | KleroEmbedType | Yes | Module type (feedback, roadmap, changelog, widget, survey) |
baseUrl | String? | No | Custom base URL |
customerToken | String? | No | JWT token for user identification |
embedConfig | Map<String, dynamic>? | No | Additional config passed to the embed |
controller | KleroEmbedController? | No | Controller for programmatic control |
onLoad | VoidCallback? | No | Called when WebView finishes loading |
KleroEmbedController Methods
| Method | Description |
|---|---|
reload() | Reload the embed |
dispose() | Clean up resources |
KleroSurvey Properties
| Property | Type | Required | Description |
|---|---|---|---|
projectSlug | String | Yes | Your Klero project slug |
surveyUlid | String | Yes | The survey's unique identifier |
baseUrl | String? | No | Custom base URL |
customerToken | String? | No | JWT token for user identification |
controller | KleroSurveyController? | No | Controller for programmatic control |
onComplete | void Function(SurveyCompletedEvent)? | No | Survey completed |
onClose | void Function(SurveyClosedEvent)? | No | Survey closed |
onError | void Function(String)? | No | Survey failed to load |
onLoad | VoidCallback? | No | Called when WebView finishes loading |
KleroSurveyController Methods
| Method | Description |
|---|---|
open([String? surveyUlid]) | Open the survey |
close() | Close the survey |
dispose() | Clean up resources |
Convenience Widgets
| Widget | Equivalent |
|---|---|
KleroFeedback | KleroEmbed(embedType: KleroEmbedType.feedback) |
KleroRoadmap | KleroEmbed(embedType: KleroEmbedType.roadmap) |
KleroChangelog | KleroEmbed(embedType: KleroEmbedType.changelog) |
Platform Setup
Android
Add internet permission to android/app/src/main/AndroidManifest.xml (usually already present):
<uses-permission android:name="android.permission.INTERNET" />iOS
No additional setup required. The SDK uses WKWebView which is available on iOS 13.0+.