- [Making App Entities Available in Spotlight](https://developer.apple.com/documentation/appintents/making-app-entities-available-in-spotlight)
Install
npx skillscat add rshankras/claude-code-apple-skills/skills-generators-deep-linking Install via the SkillsCat registry.
Generates deep linking infrastructure for iOS apps, including custom URL schemes, Universal Links, and App Intents for Siri/Shortcuts integration. It sets up the routing, intent, and Spotlight entity code needed to navigate to specific app content from external sources or voice commands. Use this when an app needs to handle inbound links or expose actions through Siri and the Shortcuts app.
Deep Linking Generator
Generate deep linking infrastructure with URL schemes, Universal Links, and App Intents for Siri/Shortcuts.
When to Use
- User wants to handle custom URL schemes (myapp://)
- User mentions Universal Links or Associated Domains
- User wants Siri Shortcuts or App Intents
- User needs to navigate to specific content from external sources
Pre-Generation Checks
Before generating, verify:
Existing Deep Link Handling
# Check for existing URL handling grep -r "onOpenURL\|open.*url\|handleOpen" --include="*.swift" | head -5URL Scheme in Info.plist
# Check for CFBundleURLTypes find . -name "Info.plist" -exec grep -l "CFBundleURLSchemes" {} \;Associated Domains Entitlement
find . -name "*.entitlements" -exec grep -l "associated-domains" {} \;
Configuration Questions
1. URL Scheme
- What custom URL scheme? (e.g.,
myapp) - This enables
myapp://path/to/contentlinks
2. Universal Links
- Yes - Handle HTTPS links (requires AASA file on server)
- No - Custom URL scheme only
3. App Intents / Siri Shortcuts
- Yes - Enable voice commands and Shortcuts app
- No - URL-based deep linking only
4. Link Types
- Profile:
/users/{id} - Content:
/items/{id} - Actions:
/actions/share,/actions/create - Custom routes based on app needs
Generated Files
Core Infrastructure
Sources/DeepLinking/
âââ DeepLinkRouter.swift # Central router
âââ DeepLink.swift # Route definitions
âââ UniversalLinkHandler.swift # Universal link processingApp Intents (Optional)
Sources/AppIntents/
âââ OpenContentIntent.swift # Open specific content
âââ AppShortcuts.swift # Shortcuts provider
âââ ContentEntity.swift # Entities for Spotlight/SiriServer Files (Universal Links)
.well-known/
âââ apple-app-site-association # AASA file templateKey Features
Route Definitions
enum DeepLink: Equatable {
case home
case profile(userId: String)
case item(itemId: String)
case settings
case action(ActionType)
enum ActionType {
case share(itemId: String)
case create
}
}URL Parsing
extension DeepLink {
init?(url: URL) {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return nil
}
let pathComponents = components.path.split(separator: "/").map(String.init)
switch pathComponents {
case ["users", let userId]:
self = .profile(userId: userId)
case ["items", let itemId]:
self = .item(itemId: itemId)
case ["settings"]:
self = .settings
default:
self = .home
}
}
}SwiftUI Integration
@main
struct MyApp: App {
@State private var router = DeepLinkRouter()
var body: some Scene {
WindowGroup {
ContentView()
.environment(router)
.onOpenURL { url in
router.handle(url)
}
}
}
}App Intents Integration
OpenIntent for Navigation
struct OpenItemIntent: OpenIntent {
static let title: LocalizedStringResource = "Open Item"
@Parameter(title: "Item")
var target: ItemEntity
func perform() async throws -> some IntentResult {
await router.navigate(to: .item(itemId: target.id))
return .result()
}
}App Shortcuts
struct AppShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: OpenItemIntent(),
phrases: [
"Open \(\.$target) in \(.applicationName)",
"Show \(\.$target)"
],
shortTitle: "Open Item",
systemImageName: "doc"
)
}
}Required Capabilities
URL Scheme (Info.plist)
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
<key>CFBundleURLName</key>
<string>com.yourcompany.myapp</string>
</dict>
</array>Universal Links (Entitlements)
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:yourapp.com</string>
<string>applinks:www.yourapp.com</string>
</array>Server Configuration (AASA)
Host at https://yourapp.com/.well-known/apple-app-site-association:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.yourcompany.yourapp",
"paths": [
"/items/*",
"/users/*",
"/share/*"
]
}
]
}
}Integration Steps
1. Basic URL Handling
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in
handleDeepLink(url)
}
}
}
}2. Universal Links (UIKit)
// In SceneDelegate
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else {
return
}
handleUniversalLink(url)
}3. App Intents Setup
- Create entities for Spotlight indexing
- Implement OpenIntent for each content type
- Define AppShortcuts for Siri phrases
- Index entities with CSSearchableIndex
Testing
URL Schemes
# Simulator
xcrun simctl openurl booted "myapp://items/123"
# Device
# Open Safari and navigate to myapp://items/123Universal Links
# Test AASA file
curl -I "https://yourapp.com/.well-known/apple-app-site-association"
# Should return Content-Type: application/json
# Validate with Apple
# Use Apple's tool or Branch.io validatorApp Intents
- Build and run on device
- Open Shortcuts app
- Your app's shortcuts should appear
- Test with Siri: "Hey Siri, [your phrase]"