Docs

Installation

Add lander_flutter to your Flutter app from pub.dev.

Set up with an AI agent

Using Claude Code, Cursor or Codex? Paste this prompt into the agent from your app's folder. It adds the package, initializes it, routes links and sets up iOS and Android, and asks you for anything it cannot read from the project.

Setup prompt
Set up Lander deep linking in this Flutter app.Lander (https://golander.link) gives the app short links that open the right screen on iOS and Android, including right after an install. The SDK is lander_flutter on pub.dev. Its README is the reference for everything below: https://pub.dev/packages/lander_flutterProject details (when a value says "ask me", ask before you use it):- Link domain: LANDER_DOMAIN, <ask me: my link domain, for example acme.golander.link>- Publishable key: <ask me: my pk_... key from API keys in the Lander dashboard>- iOS bundle ID: read it from the Xcode project- Android package name: read it from android/app/build.gradle(.kts)- Custom URL scheme: none (skip the custom scheme steps)Before changing anything, read pubspec.yaml, lib/main.dart, the router setup, ios/Runner/Info.plist, ios/Runner/*.entitlements and android/app/src/main/AndroidManifest.xml. Tell me which router the app uses and what you plan to change.1. Add the package: `flutter pub add lander_flutter`. It needs Flutter 3.38 or newer, iOS 15+ and Android API 24+. If the iOS deployment target or minSdk is lower, raise it and tell me.2. Initialize before runApp. Make main() async, call WidgetsFlutterBinding.ensureInitialized() if anything else runs first, then:   await Lander.initialize(apiKey: 'pk_...', enableLogging: kDebugMode);   Use the import 'package:lander_flutter/lander_flutter.dart'. Publishable keys (pk_test_ or pk_live_) are safe to ship in the app. Never use a secret key (sk_), the SDK rejects it. If the project already reads config from --dart-define or an env file, put the key there instead of hardcoding it.3. Route every link. Subscribe to Lander.onDeepLink once, where the router exists (for example initState of the root widget), navigate to link.route and pass the LanderLink along (with go_router: router.go(link.route, extra: link)). Cancel the subscription in dispose. Cold starts, warm starts and deferred links all arrive on this one stream, buffered until you listen, so do not also call getInitialLink unless the app needs the launch link to pick its first screen. When link.isResolved is false or the route matches no screen, ignore it instead of showing an error page.4. iOS:   - Add the Associated Domains entitlement "applinks:LANDER_DOMAIN" to the Runner target. Create or update ios/Runner/Runner.entitlements and make sure CODE_SIGN_ENTITLEMENTS points to it for the Debug, Release and Profile configurations in project.pbxproj.   - In ios/Runner/Info.plist set FlutterDeepLinkingEnabled to false, so Flutter's own handler does not navigate a second time.5. Android, in android/app/src/main/AndroidManifest.xml inside the main activity:   - Add <meta-data android:name="flutter_deeplinking_enabled" android:value="false" />.   - Add an intent-filter with android:autoVerify="true", the android.intent.action.VIEW action, the DEFAULT and BROWSABLE categories and <data android:scheme="https" android:host="LANDER_DOMAIN" />.   - Keep android:launchMode="singleTop".6. Deferred deep links need no extra code. Links with link.confidence == LanderConfidence.probabilistic are a best guess: it is fine to open the screen, but never sign the user in, apply a credit or skip a payment based on one.7. Optional, ask me first: if the app already records sign ups or purchases, also call Lander.trackEvent('purchase', properties: {...}, linkId: link.linkId) there so conversions show up in Lander. If my backend creates Lander handoffs, call Lander.claimHandoff(user.id) right after sign in and navigate to the returned link when it is not null.8. Check your work: run flutter analyze and fix what you introduced. Then give me the commands to test a link without tapping one:   xcrun simctl openurl booted "https://LANDER_DOMAIN/<slug>"   adb shell am start -a android.intent.action.VIEW -d "https://LANDER_DOMAIN/<slug>" <package name>Finish with a short list of the files you changed, and remind me what is left in the Lander dashboard: under Setup, then Platforms, add the Apple Team ID and bundle ID, plus the Android package name and the SHA-256 fingerprints of every signing key (debug, upload and the Play App Signing key), so Lander can serve apple-app-site-association and assetlinks.json for LANDER_DOMAIN.

The SDK page in the dashboard has the same prompt with your project's link domain, key prefix, bundle ID and package name already filled in. Copy it from there when you can.

Check your toolchain

lander_flutter needs Flutter 3.38 or newer (Dart 3.10), and builds for iOS 15.0+ and Android API 24+.

flutter --version

If your iOS deployment target or Android minSdk is lower, raise it before you add the package:

In Xcode, select the Runner target, then General and set Minimum Deployments to iOS 15.0. If your project uses CocoaPods, also set it in ios/Podfile:

ios/Podfile
platform :ios, '15.0'

Add the package

lander_flutter is published on pub.dev by the verified publisher golander.link. Add it with:

flutter pub add lander_flutter

Or add it to pubspec.yaml yourself and run flutter pub get:

pubspec.yaml
dependencies:
  lander_flutter: ^0.2.0

Source and issues

The source is mirrored read only at github.com/SwiftwareIO/lander_flutter. Report bugs on its issue tracker. The package is MIT licensed.

Import it

Everything you need comes from one import:

import 'package:lander_flutter/lander_flutter.dart';

It exports Lander, LanderLink, LanderShortLink, LanderConfidence, LanderException and landerSdkVersion.

What the plugin adds for you

You do not need to add any native dependencies or code by hand.

  • Android: the plugin depends on com.android.installreferrer:installreferrer (version 2.2) so it can read the Play Install Referrer once, on first launch, for deferred deep links. Link delivery hooks into your FlutterActivity automatically.
  • iOS: the plugin ships a privacy manifest (PrivacyInfo.xcprivacy) and registers for both app delegate and scene delegate callbacks. It supports Swift Package Manager and CocoaPods, so it works whichever one your Flutter project uses.

You still need to tell each OS that your app owns your Lander link domain. That is the next step.

Next steps

On this page