skills/generators/app-clip/SKILL.md
Generates App Clip targets with invocation URL handling, lightweight experiences, and full app upgrade prompts. Use when user wants NFC/QR/Safari banner invocation, instant app experiences, or App Clip Card setup.
npx skillsauth add rshankras/claude-code-apple-skills app-clipInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate production App Clip infrastructure — a lightweight version of your app invoked from NFC tags, QR codes, Safari banners, or Messages. Includes App Clip target setup, invocation URL handling, experience routing, location confirmation, and full app upgrade flow.
Use this skill when the user:
Search for existing App Clip targets:
Glob: **/*AppClip*/*.swift, **/*Clip*/*.swift
Grep: "NSUserActivityTypeBrowsingWeb" or "AppClipExperience" or "SKOverlay"
If existing App Clip target found:
Identify where the main app target lives and where to place the App Clip target alongside it.
Ask user via AskUserQuestion:
Invocation method?
Primary experience?
Include location confirmation?
Include full app upgrade prompt?
Read templates.md for production Swift code.
Read patterns.md for constraints, testing, and best practices.
Generate these files:
AppClipApp.swift — @main App struct handling invocation via .onContinueUserActivityInvocationHandler.swift — Parses invocation URL, extracts parameters, validates against registered experiencesAppClipExperience.swift — Protocol and concrete experience implementationsLocationConfirmationView.swift — CLLocationManager-based location verification for physical invocationsFullAppUpgradeView.swift — SKOverlay-based banner prompting full app downloadSharedDataManager.swift — App Group data sharing between App Clip and full appCheck project structure:
Sources/ exists -> Sources/AppClip/AppClip/ at the same levelAppClip/After generation, provide:
AppClip/
├── AppClipApp.swift # @main entry point with invocation handling
├── InvocationHandler.swift # URL parsing and parameter extraction
├── AppClipExperience.swift # Experience protocol and implementations
├── LocationConfirmationView.swift # Location verification (optional)
├── FullAppUpgradeView.swift # SKOverlay upgrade prompt (optional)
└── SharedDataManager.swift # App Group data sharing (optional)
Add App Clip Target:
{main-app-bundle-id}.ClipConfigure Associated Domains:
appclips:{your-domain.com} to both main app and App Clip entitlementsSet Up App Group:
group.{your-bundle-id} to both targets for shared dataApple-App-Site-Association (AASA) file:
https://{your-domain.com}/.well-known/apple-app-site-associationHandle invocation in the App Clip:
@main
struct MyAppClip: App {
@State private var handler = InvocationHandler()
var body: some Scene {
WindowGroup {
ContentView(experience: handler.currentExperience)
.onContinueUserActivity(
NSUserActivityTypeBrowsingWeb
) { activity in
handler.handle(activity)
}
}
}
}
Route to the correct experience:
struct ContentView: View {
let experience: (any AppClipExperience)?
var body: some View {
if let experience {
AnyView(experience.makeView())
} else {
DefaultExperienceView()
}
}
}
Share data with the full app:
// In App Clip — save order before user upgrades
SharedDataManager.shared.save(order, forKey: "pendingOrder")
// In Full App — restore after install
if let order: Order = SharedDataManager.shared.load(forKey: "pendingOrder") {
showOrder(order)
}
Prompt full app download:
FullAppUpgradeView(
appStoreID: "123456789",
benefits: [
"Order history and favorites",
"Loyalty rewards program",
"Push notification for order updates"
]
)
@Test
func invocationHandlerParsesProductURL() {
let handler = InvocationHandler()
let url = URL(string: "https://example.com/clip/product/abc123")!
let experience = handler.parseURL(url)
#expect(experience != nil)
#expect(experience?.experienceType == .previewContent)
#expect(experience?.parameters["productID"] == "abc123")
}
@Test
func invocationHandlerRejectsInvalidURL() {
let handler = InvocationHandler()
let url = URL(string: "https://other-domain.com/something")!
let experience = handler.parseURL(url)
#expect(experience == nil)
}
@Test
func sharedDataManagerRoundTrips() {
let manager = SharedDataManager(suiteName: "group.test")
let order = Order(id: "order-1", items: ["Latte", "Muffin"])
manager.save(order, forKey: "testOrder")
let loaded: Order? = manager.load(forKey: "testOrder")
#expect(loaded?.id == "order-1")
#expect(loaded?.items.count == 2)
}
Every App Clip starts from a URL. Parse it to determine what experience to show:
// URL: https://example.com/clip/order?location=store-42
// -> Route to OrderExperience with locationID = "store-42"
Users expect instant value. Show the relevant experience within 1-2 seconds, no sign-in required.
After the user completes the primary task, show an SKOverlay banner with clear benefits of the full app.
appclips: associated domain configured, and the AASA file must be hosted on the domain.xcodebuild -exportArchive or the App Thinning Size Report.generators/deep-linking — Universal link and deep link handlinggenerators/onboarding-generator — Onboarding flow for full app upgradedevelopment
US web checkout via the StoreKit External Purchase Link entitlement — currently 0% Apple commission (litigation ongoing), how to ship it safely, and how to architect for a commission flip so a future ruling is a config change, not a rewrite. Use when adding external purchase links, weighing web checkout vs IAP, or planning US-storefront pricing strategy.
tools
Revenue beyond the single-app price tag — own-app bundles, Family Sharing as a conversion lever, cross-developer bundles & suites, and institutional licensing via Group Purchases / Apple School & Business Manager. Use when a developer has multiple apps, a subscription worth sharing, complementary indie partners, or school/clinic/business buyers.
testing
Run a structured accessibility audit on an iOS/macOS app — automated XCUITest audits, Accessibility Inspector, manual VoiceOver/Dynamic Type passes, and App Store Accessibility Nutrition Label evaluation. Use before release, when preparing Nutrition Label declarations, or for EU Accessibility Act compliance.
tools
Stage-by-stage audit of an app's App Store growth machinery against a 54-item P0–P9 playbook — every item scored from an App Store Connect MCP call, a codebase check, or an explicit question to the user, then routed to the skill or command that fixes it. Read-only on App Store Connect. Use for a growth audit or scorecard, a pre-launch growth plan, a quarterly re-audit, or "which growth levers am I missing."