agentsclimarketplace

Deep links universal links

Skill almasumdev/awesome-mobile-agent-skills/.github/skills/lifecycle/deep-links-universal-links

Stack-agnostic agent skills and workflows shared across iOS, Android, Flutter, React Native, and KMP.

Install
npx -y skills add almasumdev/awesome-mobile-agent-skills --skill deep-links-universal-links

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Implementing and testing deep links on mobile - Android App Links, iOS Universal Links, custom URL schemes, attribution providers, and sunset guidance for Firebase Dynamic Links. Use when adding, debugging, or migrating deep link behavior.

SKILL.md

6.6 KB, as published. Nobody here has run it

Deep Links and Universal Links

Instructions

Deep links are the front door of a mobile app. They power marketing, referrals, support links, push notifications, and share flows. Get them wrong and none of the growth loops work.

1. Link Types

TypeiOSAndroidProperties
Custom schememyapp://myapp://Works without verification, not shareable on the web
Universal/App Linkhttps://app.example.com/...https://app.example.com/...Verified domain, opens app if installed, falls back to web
Deferred deep link3rd-party SDK3rd-party SDKCarries context through install from store
Firebase Dynamic LinksdeprecateddeprecatedSunset Aug 25, 2025. Do not build new integrations.
Branch / Adjust / AppsFlyerSupportedSupportedReplacement for FDL, attribution included

2. iOS Universal Links

  1. Host an apple-app-site-association (AASA) JSON file at https://example.com/.well-known/apple-app-site-association, served over HTTPS, no redirects, content-type application/json.
  2. Add the Associated Domains entitlement with applinks:example.com.
  3. Handle the link in SceneDelegate / SwiftUI.
{
  "applinks": {
    "details": [{
      "appIDs": ["TEAMID.com.example.app"],
      "components": [
        { "/": "/article/*" },
        { "/": "/u/*" }
      ]
    }]
  }
}
// SwiftUI
ContentView()
  .onOpenURL { url in DeepLinkRouter.shared.handle(url) }
  .onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { activity in
      if let url = activity.webpageURL { DeepLinkRouter.shared.handle(url) }
  }

3. Android App Links

  1. Declare an intent filter with android:autoVerify="true".
  2. Host assetlinks.json at https://example.com/.well-known/assetlinks.json.
  3. Verify with adb shell pm get-app-links com.example.app.
<!-- AndroidManifest.xml -->
<activity android:name=".MainActivity" android:exported="true">
  <intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" android:host="app.example.com" />
    <data android:pathPrefix="/article/" />
  </intent-filter>
</activity>
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.app",
    "sha256_cert_fingerprints": ["AB:CD:..."]
  }
}]

4. Cross-Platform Handling

// Flutter via go_router
final router = GoRouter(routes: [
  GoRoute(path: '/article/:id', builder: (_, s) => ArticleScreen(id: s.pathParameters['id']!)),
]);
// plus app_links plugin to catch initial and streamed URIs
// React Native with Expo Linking
Linking.getInitialURL().then((url) => url && router.handle(url));
Linking.addEventListener('url', ({ url }) => router.handle(url));

5. Attribution and Deferred Deep Links

If a link must carry context through a fresh install from the store, the platforms alone do not solve it. Options:

  • Branch, AppsFlyer OneLink, Adjust deep links -- full attribution and deferred deep linking.
  • Build your own with a clickthrough page that writes a short-lived token to a server and reads it on first launch (by IP+UA fingerprint or a one-time code flow).

Firebase Dynamic Links is sunsetted (August 25, 2025). Migrate to one of the above or roll your own.

6. Routing Contract

All deep links must resolve through a single router:

  • Parse the URL into a typed route.
  • Reject unknown paths gracefully (land on a sensible screen, log a metric).
  • Require auth where appropriate; store the target URL and replay after sign-in.
  • Establish a back stack so the system back returns to a reasonable place.
sealed class Route {
    data class Article(val id: String) : Route()
    data class Profile(val handle: String) : Route()
    data object Unknown : Route()
}
fun parse(uri: Uri): Route = when {
    uri.pathSegments.firstOrNull() == "article" && uri.pathSegments.size == 2 ->
        Route.Article(uri.pathSegments[1])
    uri.pathSegments.firstOrNull() == "u" && uri.pathSegments.size == 2 ->
        Route.Profile(uri.pathSegments[1])
    else -> Route.Unknown
}

7. Testing

  • iOS: xcrun simctl openurl booted https://app.example.com/article/42.
  • Android: adb shell am start -W -a android.intent.action.VIEW -d "https://app.example.com/article/42" com.example.app.
  • Custom scheme iOS: xcrun simctl openurl booted myapp://article/42.
  • Custom scheme Android: adb shell am start -a android.intent.action.VIEW -d "myapp://article/42".
  • Always test both cold start and warm start paths. They behave differently.

8. Common Bugs

  • AASA not served with the right content-type or blocked by redirects. Verify with curl -I.
  • autoVerify failing due to missing assetlinks.json for the release keystore. Both debug and release SHA-256s must be present.
  • Links opening the browser instead of the app because the user explicitly disassociated the domain. Provide a manual "open in app" fallback.
  • Universal Links failing inside apps that use in-app browsers (WKWebView, SFSafariViewController navigations). Tap-through from Safari to the app is fine; programmatic opens often are not.
  • Links arriving before the router is mounted on cold start. Buffer and replay when the navigator is ready.

9. Anti-Patterns

  • Using custom schemes for marketing links (unshareable, unverified).
  • Embedding user secrets in link paths or query strings.
  • Relying on Firebase Dynamic Links for new projects.
  • Not versioning the link namespace. Reserve a path prefix like /l/v1/ so breaking changes are possible.

Checklist

  • AASA and assetlinks.json are hosted correctly and verified in CI.
  • Associated Domains entitlement and App Links intent filter are present.
  • A single router parses and dispatches every URL.
  • Unknown links degrade gracefully.
  • Cold-start links are buffered and replayed after navigator is ready.
  • Auth-gated routes store and replay the target URL.
  • Attribution/deferred deep linking uses a supported provider (not Firebase Dynamic Links).
  • Both debug and release signing SHA-256s are in assetlinks.json.
  • Manual QA steps (simctl, adb) are documented.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.