Setting Up the Feedback SDK
What you'll learn
- Generating the Feedback SDK with optional feature voting
- Configuring the feedback endpoint via a DI module
- Submitting bug reports and general feedback with screenshot attachments
- Using shake-to-feedback and the offline queue
- Letting users vote on feature requests
Prerequisites
- An existing Archipelago monorepo (see Monorepo Scaffolding)
- Connectivity SDK recommended for offline queue drain (see Connectivity SDK Setup)
Pro Feature
feedback_sdk requires an active Pro subscription. Run archipelago auth status to confirm your tier.
Step 1: Generate the Feedback SDK
archipelago generate feedback_sdkYou will be prompted for:
- includeFeatureVoting —
trueto scaffold feature-request voting endpoints (default:true) - defaultEndpoint — your feedback API URL, e.g.
https://api.yourapp.com/feedback(default: empty — configure in DI instead)
Or use a config file:
{
"includeFeatureVoting": true,
"defaultEndpoint": ""
}archipelago generate feedback_sdk --config feedback_config.jsonStep 2: Understand the Generated Structure
features/feedback/
├── feedback_api/
│ └── lib/src/
│ ├── feedback_sdk.dart # Abstract SDK contract
│ ├── feedback_submission.dart # Submission value object
│ ├── feedback_category.dart # FeedbackCategory enum
│ ├── feedback_config.dart # Config value object
│ └── models/
│ └── feature_request.dart # (when includeFeatureVoting=true)
└── feedback_impl/
└── lib/src/
├── feedback_sdk_impl.dart # HTTP + offline queue impl
└── di/ # GetIt moduleStep 3: Configure the Endpoint
Provide FeedbackConfig in a DI module before FeedbackImplPackageModule is registered. Create app_feedback_module.dart in your shell app:
@module
abstract class AppFeedbackModule {
@lazySingleton
FeedbackConfig get feedbackConfig => const FeedbackConfig(
endpoint: 'https://api.yourapp.com/feedback',
attachAppVersion: true,
attachDeviceInfo: true,
);
}Then register in bootstrap.dart:
import 'package:feedback_impl/feedback_impl.dart';
FeatureRegistry.register(FeedbackImpl());Step 4: Submit Feedback
Inject FeedbackSDK via GetIt and call submit():
final feedbackSDK = getIt<FeedbackSDK>();
await feedbackSDK.submit(
FeedbackSubmission(
text: 'The checkout button is hard to find',
category: FeedbackCategory.bug,
screenshotPath: await _captureScreenshot(),
),
);FeedbackCategory values: bug, general, featureRequest, question.
Leave screenshotPath null to submit without an attachment.
Step 5: Offline Queue
The SDK queues submissions in SharedPreferences when the device is offline. No extra setup is required — the queue drains automatically when connectivity is restored.
If you have the Connectivity SDK installed, wire the state stream in for faster drain triggering:
connectivitySDK.stateStream.listen((state) {
feedbackSDK.recordConnectivity(online: state.isOnline);
});Without this wiring, the SDK polls on the next submit() call.
Step 6: Shake-to-Feedback (Optional)
Add the shake package to your shell app's pubspec.yaml:
dependencies:
shake: ^2.2.0Then start the detector after your DI is ready:
ShakeDetector.autoStart(
onPhoneShake: () async {
final text = await _promptUserForText();
await feedbackSDK.submit(
FeedbackSubmission(
text: text,
category: FeedbackCategory.general,
),
);
},
);_promptUserForText() should show a dialog — use whatever UI pattern fits your app.
Step 7: Feature Voting (when includeFeatureVoting=true)
Fetch open feature requests and let users upvote them:
final requests = await feedbackSDK.getFeatureRequests();
// Display in a list, then on tap:
final result = await feedbackSDK.voteOnFeatureRequest(requests.first.id);Votes are locally deduplicated: calling voteOnFeatureRequest() a second time for the same requestId returns FeatureRequestVoteResult.alreadyVoted without hitting the network.
switch (result) {
case FeatureRequestVoteResult.success:
showSnackbar('Thanks for your vote!');
case FeatureRequestVoteResult.alreadyVoted:
showSnackbar('You\'ve already voted for this.');
case FeatureRequestVoteResult.error:
showSnackbar('Something went wrong, try again.');
}Common Customizations
| Customization | Where to Change |
|---|---|
| Add user identity to submissions | Set userId on FeedbackConfig in your DI module |
| Custom categories | Extend FeedbackCategory in a local fork of the api package |
| Rate-limit shake trigger | Track last submission timestamp before calling submit() |
| Disable in release builds | Wrap ShakeDetector.autoStart with !kReleaseMode |
Next Steps
- Set up the Home Widget to surface key info on the home screen
- Configure monitoring to track feedback submission failures