DeeplinkX

pub package Coverage Status License: MIT GitHub Issues GitHub Stars Platform

DeeplinkX Logo

Type-safe deeplinks to external apps β€” with automatic store fallback, across every Flutter platform.

🌐 Live Demo  Β·  πŸ“– API Reference  Β·  πŸ“‹ Changelog  Β·  βž• Request an App

What does the X stand for? External. DeeplinkX is specifically built for launching deeplinks into other apps, not handling incoming links into your own.


Table of Contents


Features

  • Typed API β€” launch any supported app or in-app action with strongly-typed Dart calls; no URL string maintenance.
  • Smart fallback β€” automatically redirects to the app store or a web URL when the target app is not installed.
  • Installation check β€” query whether any supported app is present on the device before attempting a launch.
  • Store redirect β€” send users to the correct store for their platform (iOS App Store, Google Play, Huawei AppGallery, and more).
  • Map provider fallback β€” try navigation apps in your preferred order; the first installed one wins.
  • Cross-platform β€” works on iOS, Android, macOS, Windows, Linux, and Web from a single package.
  • 7 supported stores β€” iOS App Store, Mac App Store, Microsoft Store, Google Play Store, Huawei AppGallery, Cafe Bazaar, Myket.
  • 15 supported apps β€” Facebook, Instagram, LinkedIn, WhatsApp, Telegram, Twitter, YouTube, TikTok, Pinterest, Zoom, Slack, Google Maps, Waze, Apple Maps, Sygic.

Demo

Try the live web demo or build the example on a real device for the full experience β€” app installation checks require a native platform.

Instagram Profile
Instagram profile deeplink demo
Telegram Profile
Telegram profile deeplink demo
Facebook App
Facebook app deeplink demo
YouTube Video
YouTube video deeplink demo
Facebook Web Fallback
Facebook web fallback deeplink demo
iOS App Store Page
iOS App Store deeplink demo

Install

flutter pub add deeplink_x

Then import the package wherever you need it:

import 'package:deeplink_x/deeplink_x.dart';

Quick Start

The example below opens a Telegram profile on iOS. If Telegram is not installed, the user is redirected to the App Store.

Step 1 β€” declare the URL scheme in ios/Runner/Info.plist:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>tg</string>
    <string>itms-apps</string>
</array>

Step 2 β€” launch the action:

final deeplinkX = DeeplinkX();

final launched = await deeplinkX.launchAction(
  Telegram.openProfile(username: 'username', fallbackToStore: true),
);

That's it. DeeplinkX resolves the platform, checks installation, and handles the fallback for you.


Core Concepts

The three-tier fallback system

DeeplinkX applies the following strategy on every launch, in order:

  1. Native deeplink β€” opens the app directly using a custom URL scheme, App Link, or Android Intent when the app is installed.
  2. Store fallback β€” if fallbackToStore: true and the app is not installed, redirects to the appropriate app store for the current platform.
  3. Web fallback β€” if no store redirect applies, opens the web URL for the action (when one exists).

Pass disableFallback: true to any launch method to skip steps 2 and 3 entirely and attempt only the native path.

Important: When fallbackToStore: true is set and a custom scheme is removed or changed by the app vendor, DeeplinkX will redirect to the store rather than the web fallback. Set fallbackToStore: false if you always want the web URL as the fallback destination.

Custom URL schemes and Android Intents let DeeplinkX reliably check whether an app is installed before attempting a launch, so the fallback logic works correctly. Universal links cannot be checked in advance and open a browser tab on failure. See the full explanation in Why Custom Schemes Instead of Universal Links?.


Recipes

1. Launch an app action

Open a specific screen inside an app. Falls back to the store if the app is not installed:

final deeplinkX = DeeplinkX();

// Open a Telegram profile
await deeplinkX.launchAction(
  Telegram.openProfile(username: 'flutter', fallbackToStore: true),
);

// Open a YouTube video
await deeplinkX.launchAction(
  YouTube.openVideo(videoId: 'dQw4w9WgXcQ', fallbackToStore: true),
);

// Open a WhatsApp chat
await deeplinkX.launchAction(
  WhatsApp.chat(phoneNumber: '1234567890', fallbackToStore: true),
);

2. Launch an app

Open a supported app without targeting a specific screen:

await deeplinkX.launchApp(
  Instagram.open(fallbackToStore: true),
);

3. Check if an app is installed

final isInstalled = await deeplinkX.isAppInstalled(LinkedIn());

if (isInstalled) {
  await deeplinkX.launchAction(
    LinkedIn.openProfile(profileId: 'johndoe'),
  );
}

4. Redirect to an app store

Send users to the correct store for their platform. DeeplinkX picks the matching entry automatically:

await deeplinkX.redirectToStore(
  storeActions: [
    IOSAppStore.openAppPage(appId: '389801252', appName: 'instagram'),
    PlayStore.openAppPage(packageName: 'com.instagram.android'),
    HuaweiAppGalleryStore.openAppPage(
      packageName: 'com.instagram.android',
      appId: 'C101162369',
    ),
    MacAppStore.openAppPage(appId: '1274495053', appName: 'instagram'),
    MicrosoftStore.openAppPage(productId: '9nblggh5l9xt'),
    CafeBazaarStore.openAppPage(packageName: 'com.instagram.android'),
    MyketStore.openAppPage(packageName: 'com.instagram.android'),
  ],
);

5. Map provider fallback

Try navigation apps in priority order. DeeplinkX attempts each one natively and moves to the next if the app is not installed:

final deeplinkX = DeeplinkX();

const origin = Coordinate(latitude: 35.6892, longitude: 51.3890);
const destination = Coordinate(latitude: 35.7000, longitude: 51.4000);

// View a location
await deeplinkX.launchMapViewAction(
  actions: [
    GoogleMaps.view(coordinate: origin),
    AppleMaps.view(coordinate: origin),
    Waze.view(coordinate: origin),
    Sygic.view(coordinate: origin),
  ],
);

// Search for a place
await deeplinkX.launchMapSearchAction(
  actions: [
    GoogleMaps.search(query: 'Central Park'),
    AppleMaps.search(query: 'Central Park'),
    Waze.search(query: 'Central Park'),
  ],
);

// Get directions by address
await deeplinkX.launchMapDirectionsAction(
  actions: [
    GoogleMaps.directions(destination: 'Eiffel Tower, Paris'),
    AppleMaps.directions(destination: 'Eiffel Tower, Paris'),
    Waze.directions(destination: 'Eiffel Tower, Paris'),
  ],
);

// Get directions by coordinates
await deeplinkX.launchMapDirectionsWithCoordsAction(
  actions: [
    GoogleMaps.directionsWithCoords(destination: destination),
    AppleMaps.directionsWithCoords(destination: destination),
    Waze.directionsWithCoords(destination: destination),
    Sygic.directionsWithCoords(destination: destination),
  ],
);
Method Supported apps
launchMapViewAction Google Maps, Apple Maps, Waze, Sygic
launchMapSearchAction Google Maps, Apple Maps, Waze
launchMapDirectionsAction Google Maps, Apple Maps, Waze
launchMapDirectionsWithCoordsAction Google Maps, Apple Maps, Waze, Sygic

Supported Apps and Actions

Category App Actions
Stores iOS App Store Open app page, rate app
Mac App Store Open app page, rate app
Microsoft Store Open app page, rate app
Google Play Store Open app page
Huawei AppGallery Open app page
Cafe Bazaar Open app page
Myket Open app page, rate app
Social Telegram Open profile by username, open profile by phone number, send message
Instagram Open profile by username
WhatsApp Chat with phone number, share text content
Facebook Open profile by ID, open profile by username, open page, open group, open event
YouTube Open video, open channel, open playlist, search
Twitter Open profile by username, open tweet by ID, search
Pinterest Open profile by username, open pin, open board by ID, search
TikTok Open profile by username, open video, open tag
Zoom Join meeting by ID
Slack Open team, open channel, open user
LinkedIn Open profile page, open company page
Navigation Google Maps View map, search location, directions, directions with coordinates
Apple Maps View map, search location, directions, directions with coordinates
Waze View map, search, directions, directions with coordinates
Sygic View map, directions with coordinates

Platform Configuration

Some platforms require you to declare URL schemes or package visibility before the OS allows installation checks.

Platform File
iOS ios/Runner/Info.plist
Android android/app/src/main/AndroidManifest.xml
macOS macos/Runner/Info.plist

Windows, Linux, and Web do not require additional configuration.

Each app's documentation page (linked in Documentation) lists the exact schemes and package names to declare. As a reference, here is the iOS entry for Telegram and the App Store:

<!-- ios/Runner/Info.plist -->
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>tg</string>
    <string>itms-apps</string>
</array>

And the Android entry for Instagram:

<!-- android/app/src/main/AndroidManifest.xml -->
<queries>
    <package android:name="com.instagram.android" />
</queries>

DeeplinkX prefers custom URL schemes, App Links, and Android Intents over plain HTTPS universal links for several concrete reasons:

Direct app launch, no browser flash. Custom schemes and App Links open the native app without routing through a browser first, which eliminates the redirect flicker that users see with universal links. The result is a smoother, more native-feeling experience.

No "Open with…" dialog on Android. Android Intents let DeeplinkX target the exact app package, so the system launches it directly. Universal links can show a disambiguation dialog when multiple apps claim the same domain.

Reliable installation check. DeeplinkX can query canLaunch for a custom scheme or check for a package name before attempting a launch. Universal links return true even when the app is absent, because the browser will handle them β€” making fallback logic unreliable.

Resilience to scheme changes. Custom schemes are unofficial and can be deprecated by app vendors. DeeplinkX always pairs a custom scheme with a web fallback URL, so if a scheme disappears, users are still redirected somewhere useful rather than landing on an error.

Best of both. DeeplinkX uses the speed and precision of custom schemes for native launches and the reliability of web URLs as the last-resort fallback, giving users the best possible path to the content regardless of what is installed.


DeeplinkX vs url_launcher

url_launcher is a general-purpose URL launcher. DeeplinkX is purpose-built for external app deeplinks and goes further in every dimension that matters for that use case:

DeeplinkX url_launcher
Typed API for popular apps βœ… 15 apps, no URL maintenance ❌ Raw URLs only
Automatic store / web fallback βœ… Built in ❌ Manual implementation required
Installation check βœ… isAppInstalled() ⚠️ canLaunchUrl() β€” unreliable for HTTPS schemes
Android Intent support βœ… Advanced intent options ⚠️ Basic intent launching only
macOS custom scheme check βœ… Supported ❌ Not supported
Map provider fallback βœ… Try multiple apps in order ❌ Not available
Store redirect utility βœ… Per-platform store routing ❌ Not available

In practice: a store redirect with url_launcher requires you to detect the platform, look up each store URL format, handle edge cases for Huawei devices, and write that logic for every app in your project. DeeplinkX handles all of it with one method call.


Missing an App?

If DeeplinkX does not support the app, store, or navigation provider you need, open a new app request. Include the app name, target platforms, known URL schemes or App Link patterns, store links, and the actions you want to launch.


Documentation

Per-app documentation covering URL schemes, required configuration, and fallback behavior is available in doc/apps:

Stores

Store Link
iOS App Store ios_app_store.md
Mac App Store mac_app_store.md
Microsoft Store microsoft_store.md
Google Play Store play_store.md
Huawei AppGallery huawei_app_gallery_store.md
Cafe Bazaar cafe_bazaar_store.md
Myket myket_store.md

Apps

App Link
Facebook facebook.md
Instagram instagram.md
Telegram telegram.md
WhatsApp whatsapp.md
LinkedIn linkedin.md
YouTube youtube.md
Twitter twitter.md
Pinterest pinterest.md
TikTok tiktok.md
Zoom zoom.md
Slack slack.md
Google Maps google_maps.md
Waze waze.md
Apple Maps apple_maps.md
Sygic sygic.md

Full API reference is on pub.dev.


Contributing

Contributions are welcome. To get started:

  1. Fork the repository.
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Commit your changes: git commit -m 'Add my feature'
  4. Push to the branch: git push origin feature/my-feature
  5. Open a Pull Request.

Please check existing issues before opening a new one.


Feedback

If DeeplinkX works well for you, feels confusing in places, or is missing something important for your app, please share it through the feedback form. User feedback directly shapes the package API and documentation.


License

This project is licensed under the MIT License. See LICENSE for details.

Libraries

A cross-platform deeplink plugin that supports various apps and platforms.