npx claudepluginhub davidortinau/maui-skills --plugin maui-skillsThis skill uses the workspace's default tool permissions.
- **`AutoVerify = true` is required** on the `IntentFilter` for App Links (not
Provides patterns for mobile deep linking including Android App Links, intent filters, assetlinks.json, Kotlin handlers, iOS Universal Links, URI schemes, and navigation.
Implements deep linking in Capacitor apps with custom URL schemes, iOS Universal Links, Android App Links, and navigation handling. Use when opening apps from external links.
Guides calling platform-specific native APIs in .NET MAUI apps using partial classes, conditional compilation, multi-targeting, and DI patterns for Android, iOS, Mac Catalyst, Windows.
Share bugs, ideas, or general feedback.
AutoVerify = true is required on the IntentFilter for App Links (not
just deep links). Without it, Android shows a disambiguation dialog instead
of opening your app directly.OnCreate and OnNewIntent.
OnCreate fires for cold starts; OnNewIntent fires when the app is already
running. Missing either means links silently fail in one scenario.// ❌ Only handles cold-start links
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
HandleDeepLink(Intent);
}
// ✅ Handles both cold-start and warm-start links
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
HandleDeepLink(Intent);
}
protected override void OnNewIntent(Intent? intent)
{
base.OnNewIntent(intent);
HandleDeepLink(intent);
}
assetlinks.json accordingly or verification silently fails.adb shell pm get-app-links com.example.myapp
Look for verified status, not just ask.?mode=developer query param or
Apple's CDN diagnostics: swcutil dl -d example.com.FinishedLaunching, ContinueUserActivity,
and SceneWillConnect. Missing any one causes links to fail for specific
app states (cold start, background resume, or scene-based launch).applinks: prefix is required in the Associated Domains entitlement.
Writing just example.com instead of applinks:example.com silently fails.MainThread.BeginInvokeOnMainThreadDeep link callbacks can fire on background threads. Shell navigation must run on the main thread.
// ❌ May crash — GoToAsync called off the main thread
static void HandleUniversalLink(string? url)
{
if (string.IsNullOrEmpty(url)) return;
Shell.Current.GoToAsync(MapToRoute(url));
}
// ✅ Dispatch to main thread
static void HandleUniversalLink(string? url)
{
if (string.IsNullOrEmpty(url)) return;
MainThread.BeginInvokeOnMainThread(async () =>
await Shell.Current.GoToAsync(MapToRoute(url)));
}
Register Shell routes in AppShell constructor before any deep link can
fire. If the route doesn't exist, GoToAsync throws silently or navigates
to root.
| Approach | Verified | Fallback to browser | Recommended |
|---|---|---|---|
Custom URI scheme (myapp://) | No | No | Only for app-to-app communication |
Android App Links (https://) | Yes | Yes | ✅ Production web links |
iOS Universal Links (https://) | Yes | Yes | ✅ Production web links |
⚠️ Custom URI schemes are not verified — any app can register the same scheme. Use
https://App Links / Universal Links for user-facing URLs.
IntentFilter has AutoVerify = true on MainActivityassetlinks.json at /.well-known/ with correct SHA-256 for current signing keyOnCreate and OnNewIntentadb shell pm get-app-linksapplinks:example.com in Associated Domains entitlement (not just example.com)/.well-known/apple-app-site-association with correct Team ID