Universal Links & App Links for the Magic Framework.
One unified API for deep linking on iOS and Android — powered by app_links.
Website · Docs · pub.dev · Issues · Discussions
Alpha —
magic_deeplinkis under active development. APIs may change between minor versions until1.0.0.
Setting up deep links in Flutter means dealing with platform-specific manifests, JSON files hosted on your server, parsing URIs in multiple places, and wiring it all together. Every project reinvents the same boilerplate.
Magic Deeplink gives you a single, declarative config file. One CLI command generates the server-side files. One service provider boots everything. Handlers follow a clean chain-of-responsibility pattern — the first match wins.
Config-driven deep linking. Define your domain, paths, and platform credentials once. Magic Deeplink handles the rest.
| Feature | Description | |
|---|---|---|
| 🔗 | Unified API | Single interface for handling deep links on iOS and Android |
| 🔌 | Driver Pattern | Extensible driver architecture — swap app_links for any custom driver |
| 🚥 | Route Handler | Automatically maps deep link paths to Magic Routes |
| 🔔 | OneSignal Integration | Seamless handling of notification click actions via magic_notifications |
| 🛠️ | CLI Tools | Auto-generate apple-app-site-association and assetlinks.json |
| ⚙️ | Config-Driven | All settings in one Dart config file — no platform manifest editing |
| 🧩 | Handler Chain | Register custom handlers with canHandle / handle — first match wins |
| 📦 | Pure Dart | No native platform code — platform support via app_links package |
dependencies:
magic_deeplink: ^0.0.1dart run magic_deeplink:installThis generates lib/config/deeplink.dart, injects DeeplinkServiceProvider into lib/config/app.dart, and wires the deeplinkConfig factory into lib/main.dart.
The DeeplinkServiceProvider is automatically registered during install. On app boot, it:
- Creates the configured driver (
app_linksby default) - Initializes the driver with your config
- Listens for incoming deep links
- Routes them through your registered handlers
That's it — deep links now work across iOS and Android.
After running the install command, edit lib/config/deeplink.dart:
Map<String, dynamic> get deeplinkConfig => {
'deeplink': {
'enabled': true,
'driver': 'app_links',
'domain': 'example.com',
'scheme': 'https',
'ios': {
'team_id': 'ABC123XYZ',
'bundle_id': 'com.example.app',
},
'android': {
'package_name': 'com.example.app',
'sha256_fingerprints': [
'AA:BB:CC:...',
],
},
'paths': [
'/monitors/*',
'/status-pages/*',
'/invite/*',
],
},
};All values are read at runtime via ConfigRepository — no hardcoded strings scattered across your codebase.
Universal Links (iOS) and App Links (Android) require verification files hosted on your domain.
Generate them with one command:
dart run magic_deeplink:generate --output ./publicThis creates two files:
| File | Platform | Purpose |
|---|---|---|
apple-app-site-association |
iOS | Universal Links verification |
assetlinks.json |
Android | App Links verification |
Upload these to the root or .well-known/ directory of your web server so that https://example.com/.well-known/apple-app-site-association and https://example.com/.well-known/assetlinks.json are publicly accessible.
Scaffolds the deeplink configuration into your Magic project.
dart run magic_deeplink:installWhat it does:
- Generates
lib/config/deeplink.dartconfig file - Injects
DeeplinkServiceProviderintolib/config/app.dart - Injects
deeplinkConfigfactory intolib/main.dart
| Flag | Short | Description |
|---|---|---|
--force |
-f |
Overwrite existing configuration file |
Generates platform verification files from your config.
dart run magic_deeplink:generate --output ./publicReads configuration from lib/config/deeplink.dart first. CLI flags override config file values.
| Flag | Short | Default | Description |
|---|---|---|---|
--output |
-o |
public |
Output directory for generated files |
--root |
. |
Project root directory | |
--team-id |
— | Apple Developer Team ID | |
--bundle-id |
— | iOS app bundle identifier | |
--package-name |
— | Android package name | |
--sha256-fingerprints |
— | SHA-256 certificate fingerprints (multi) | |
--paths |
['/*'] |
Paths to handle (multi) |
Register your own handlers for specific deep link patterns:
class InviteHandler extends DeeplinkHandler {
@override
bool canHandle(Uri uri) {
return uri.path.startsWith('/invite/');
}
@override
Future<bool> handle(Uri uri) async {
final code = uri.pathSegments.last;
// Handle invite code...
return true;
}
}
// In your AppServiceProvider or main.dart:
DeeplinkManager().registerHandler(InviteHandler());Handlers follow the chain-of-responsibility pattern. The first handler where canHandle returns true processes the URI. Return true from handle to indicate success, false to pass to the next handler.
If magic_notifications is installed and bound in the container, magic_deeplink automatically registers an OneSignalDeeplinkHandler that processes notification click actions containing deep link URLs.
No extra configuration needed — the provider detects the binding at boot time and wires everything up.
To send a deep link via OneSignal, add the url or deep_link field to your notification payload.
App launch → DeeplinkServiceProvider.boot()
→ reads config via ConfigRepository
→ creates AppLinksDriver
→ driver.initialize(config)
→ listens driver.onLink stream → manager.handleUri()
→ first matching handler wins (canHandle → handle)
→ delays initial link via Future.delayed(Duration.zero) for router readiness
→ optional: OneSignal handler if magic_notifications bound
Key patterns:
| Pattern | Implementation |
|---|---|
| Singleton Manager | DeeplinkManager — central orchestrator |
| Strategy (Driver) | AppLinksDriver implements DeeplinkDriver contract |
| Chain of Responsibility | Handlers checked in order — first match wins |
| Service Provider | Two-phase bootstrap: register() (sync) → boot() (async) |
| IoC Container | All bindings via app.singleton() / app.make() |
| Document | Description |
|---|---|
| Installation | Adding the package and running the installer |
| Configuration | Config file reference and options |
| Drivers | Driver contract and AppLinksDriver details |
| Handlers | Built-in handlers and writing custom ones |
| CLI Tools | Install and generate command reference |
| Deeplink Manager | Manager singleton and handler orchestration |
| Service Provider | Bootstrap lifecycle and IoC bindings |
Contributions are welcome! Please see the issues page for open tasks or to report bugs.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Write tests following the TDD flow — red, green, refactor
- Ensure all checks pass:
flutter test,dart analyze,dart format . - Submit a pull request
Magic Deeplink is open-sourced software licensed under the MIT License.
Built with care by FlutterSDK
If Magic Deeplink helps your project, consider giving it a star on GitHub.