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 taiberium/claude_code_setting 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 upgradetools
Generates multi-step onboarding flows with persistence for iOS/macOS apps. Use when user wants to add onboarding, welcome screens, or first-launch experience.
tools
Generates an offline operation queue with persistence, automatic retry on connectivity, and conflict resolution. Use when user needs offline-first behavior, queued mutations, or pending operations that sync when back online.
development
Generates offer code distribution strategies and configuration guides for subscription and IAP promotions — including partner campaigns, influencer programs, and email re-engagement. Use when setting up offer codes for distribution.
tools
Generates a protocol-based networking layer with async/await, error handling, and swappable implementations. Use when user wants to add API client, networking, or HTTP layer.