Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
cap-go avatar

Capacitor Deep Linking

  • 586 installs
  • 57 repo stars
  • Updated July 13, 2026
  • cap-go/capgo-skills

capacitor-deep-linking is a Claude Code skill that implements deep links, universal links, and custom URL schemes in Capacitor apps for developers who need external links to open specific in-app routes.

About

capacitor-deep-linking is a Capacitor mobile skill from cap-go/capgo-skills covering iOS Universal Links, Android App Links, custom URL schemes, and in-app navigation handling when users open the app from shared or marketing links. The skill compares link types by platform, format, and whether a server-hosted association file is required. Developers reach for capacitor-deep-linking when adding share links, marketing campaign URLs, or OAuth return paths that must land on the correct screen inside a Capacitor shell. It documents platform-specific setup steps, routing patterns, and troubleshooting for links that fail to open the app or drop users on the wrong view.

  • Complete guide covering custom URL schemes, iOS Universal Links, and Android App Links
  • Includes installation of @capacitor/app plugin and sync steps
  • Shows how to listen for appUrlOpen events and parse incoming URLs
  • Provides platform-specific configuration patterns for iOS and Android
  • Handles both custom schemes (myapp://) and HTTPS-based universal/app links

Capacitor Deep Linking by the numbers

  • 586 all-time installs (skills.sh)
  • Ranked #284 of 1,039 Mobile Development skills by installs in the Skillselion catalog
  • Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cap-go/capgo-skills --skill capacitor-deep-linking

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs586
repo stars57
Last updatedJuly 13, 2026
Repositorycap-go/capgo-skills

How do you implement deep links in Capacitor apps?

Correctly implement deep links, universal links, and custom URL schemes so their Capacitor mobile app can be opened from external links.

Who is it for?

Capacitor developers wiring marketing, share, or OAuth return URLs into iOS and Android app routes.

Skip if: Pure React Native or Flutter projects that do not use the Capacitor runtime.

When should I use this skill?

A developer asks about deep links, universal links, app links, URL schemes, or opening a Capacitor app from external links.

What you get

Universal Link and App Link configuration, custom scheme handlers, and in-app route navigation from external URLs.

  • Link handler configuration
  • Platform association setup steps

Files

SKILL.mdMarkdownGitHub ↗

Deep Linking in Capacitor

Implement deep links, universal links, and app links in Capacitor apps.

When to Use This Skill

  • User wants deep links
  • User needs universal links
  • User asks about URL schemes
  • User wants to open app from links
  • User needs share links

Types of Deep Links

TypePlatformFormatRequires Server
Custom URL SchemeBothmyapp://pathNo
Universal LinksiOShttps://myapp.com/pathYes
App LinksAndroidhttps://myapp.com/pathYes

Quick Start

Install Plugin

npm install @capacitor/app
npx cap sync

Handle Deep Links

import { App } from '@capacitor/app';

// Listen for deep link opens
App.addListener('appUrlOpen', (event) => {
  console.log('App opened with URL:', event.url);

  // Parse and navigate
  const url = new URL(event.url);
  handleDeepLink(url);
});

function handleDeepLink(url: URL) {
  // Custom scheme: myapp://product/123
  // Universal link: https://myapp.com/product/123

  const path = url.pathname || url.host + url.pathname;

  // Route based on path
  if (path.startsWith('/product/')) {
    const productId = path.split('/')[2];
    navigateTo(`/product/${productId}`);
  } else if (path.startsWith('/user/')) {
    const userId = path.split('/')[2];
    navigateTo(`/profile/${userId}`);
  } else if (path === '/login') {
    navigateTo('/login');
  } else {
    navigateTo('/');
  }
}

Custom URL Scheme

iOS Configuration

<!-- ios/App/App/Info.plist -->
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>com.yourcompany.yourapp</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>myapp</string>
            <string>myapp-dev</string>
        </array>
    </dict>
</array>

Android Configuration

<!-- android/app/src/main/AndroidManifest.xml -->
<activity android:name=".MainActivity">
    <!-- Deep link intent filter -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="myapp" />
    </intent-filter>
</activity>

Test Custom Scheme

# iOS Simulator
xcrun simctl openurl booted "myapp://product/123"

# Android
adb shell am start -a android.intent.action.VIEW -d "myapp://product/123"

Universal Links (iOS)

1. Enable Associated Domains

In Xcode: 1. Select App target 2. Signing & Capabilities 3. + Capability > Associated Domains 4. Add: applinks:myapp.com

2. Create apple-app-site-association

Host at https://myapp.com/.well-known/apple-app-site-association:

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "TEAMID.com.yourcompany.yourapp",
        "paths": [
          "/product/*",
          "/user/*",
          "/invite/*",
          "NOT /api/*"
        ]
      }
    ]
  }
}

Requirements:

  • Served over HTTPS
  • Content-Type: application/json
  • No redirects
  • File at root domain

3. Info.plist

<!-- ios/App/App/Info.plist -->
<key>com.apple.developer.associated-domains</key>
<array>
    <string>applinks:myapp.com</string>
    <string>applinks:www.myapp.com</string>
</array>

Verify Universal Links

# Validate AASA file
curl -I https://myapp.com/.well-known/apple-app-site-association

# Check Apple CDN cache
curl "https://app-site-association.cdn-apple.com/a/v1/myapp.com"

App Links (Android)

1. Create assetlinks.json

Host at https://myapp.com/.well-known/assetlinks.json:

[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.yourcompany.yourapp",
      "sha256_cert_fingerprints": [
        "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99"
      ]
    }
  }
]

Get SHA256 Fingerprint

# Debug keystore
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

# Release keystore
keytool -list -v -keystore release.keystore -alias your-alias

# From APK
keytool -printcert -jarfile app-release.apk

2. AndroidManifest.xml

<!-- android/app/src/main/AndroidManifest.xml -->
<activity android:name=".MainActivity">
    <!-- App Links intent filter -->
    <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" />
        <data android:host="myapp.com" />
        <data android:pathPrefix="/product" />
        <data android:pathPrefix="/user" />
        <data android:pathPrefix="/invite" />
    </intent-filter>
</activity>

Verify App Links

# Validate assetlinks.json
curl https://myapp.com/.well-known/assetlinks.json

# Use Google's validator
https://developers.google.com/digital-asset-links/tools/generator

# Check link handling on device
adb shell pm get-app-links com.yourcompany.yourapp

Advanced Routing

React Router Integration

import { App } from '@capacitor/app';
import { useHistory } from 'react-router-dom';
import { useEffect } from 'react';

function DeepLinkHandler() {
  const history = useHistory();

  useEffect(() => {
    App.addListener('appUrlOpen', (event) => {
      const url = new URL(event.url);
      const path = getPathFromUrl(url);

      // Navigate using React Router
      history.push(path);
    });

    // Check if app was opened with URL
    App.getLaunchUrl().then((result) => {
      if (result?.url) {
        const url = new URL(result.url);
        const path = getPathFromUrl(url);
        history.push(path);
      }
    });
  }, []);

  return null;
}

function getPathFromUrl(url: URL): string {
  // Handle both custom scheme and https
  if (url.protocol === 'myapp:') {
    return '/' + url.host + url.pathname;
  }
  return url.pathname + url.search;
}

Vue Router Integration

import { App } from '@capacitor/app';
import { useRouter } from 'vue-router';
import { onMounted } from 'vue';

export function useDeepLinks() {
  const router = useRouter();

  onMounted(async () => {
    App.addListener('appUrlOpen', (event) => {
      const path = parseDeepLink(event.url);
      router.push(path);
    });

    const launchUrl = await App.getLaunchUrl();
    if (launchUrl?.url) {
      const path = parseDeepLink(launchUrl.url);
      router.push(path);
    }
  });
}

Deferred Deep Links

Handle links when app wasn't installed:

import { App } from '@capacitor/app';
import { Preferences } from '@capacitor/preferences';

// On first launch, check for deferred link
async function checkDeferredDeepLink() {
  const { value: isFirstLaunch } = await Preferences.get({ key: 'firstLaunch' });

  if (isFirstLaunch !== 'false') {
    await Preferences.set({ key: 'firstLaunch', value: 'false' });

    // Check with your attribution service
    const deferredLink = await fetchDeferredLink();
    if (deferredLink) {
      handleDeepLink(new URL(deferredLink));
    }
  }
}

Query Parameters

App.addListener('appUrlOpen', (event) => {
  const url = new URL(event.url);

  // Get query parameters
  const source = url.searchParams.get('source');
  const campaign = url.searchParams.get('campaign');
  const referrer = url.searchParams.get('ref');

  // Track attribution
  analytics.logEvent('deep_link_open', {
    path: url.pathname,
    source,
    campaign,
    referrer,
  });

  // Navigate with state
  navigateTo(url.pathname, {
    state: { source, campaign, referrer },
  });
});

OAuth Callback Handling

// Handle OAuth redirect
App.addListener('appUrlOpen', async (event) => {
  const url = new URL(event.url);

  if (url.pathname === '/oauth/callback') {
    const code = url.searchParams.get('code');
    const state = url.searchParams.get('state');
    const error = url.searchParams.get('error');

    if (error) {
      handleOAuthError(error);
      return;
    }

    if (code && validateState(state)) {
      await exchangeCodeForToken(code);
      navigateTo('/home');
    }
  }
});

Testing

Test Matrix

ScenarioCommand
Custom schememyapp://path
Universal link cold startTap link with app closed
Universal link warm startTap link with app in background
Universal link in SafariType URL in Safari
App link cold startTap link with app closed
App link in ChromeTap link in Chrome

Debug Tools

# iOS: Check associated domains entitlement
codesign -d --entitlements - App.app | grep associated-domains

# iOS: Reset Universal Links cache
xcrun simctl erase all

# Android: Check verified links
adb shell dumpsys package d | grep -A5 "Package: com.yourcompany.yourapp"

Common Issues

IssueSolution
Universal Links not workingCheck AASA file, SSL, entitlements
App Links not verifiedCheck assetlinks.json, fingerprint
Links open in browserCheck intent-filter, autoVerify
Cold start not handledUse App.getLaunchUrl()
Simulator issuesReset simulator, rebuild app

Resources

  • Capacitor App Plugin: https://capacitorjs.com/docs/apis/app
  • Universal Links Guide: https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app
  • Android App Links: https://developer.android.com/training/app-links
  • Digital Asset Links Validator: https://developers.google.com/digital-asset-links/tools/generator

Related skills

FAQ

Which deep link types does capacitor-deep-linking cover?

capacitor-deep-linking covers iOS Universal Links, Android App Links, and custom URL schemes. The skill explains platform format differences and when server-hosted association files are required.

When should developers load capacitor-deep-linking?

Developers should load capacitor-deep-linking when users need deep links, universal links, share links, or custom URL schemes that open a Capacitor app on a specific in-app route.

Mobile Developmentintegrationsfrontend

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.