From apple-dev
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 claudepluginhub autisticaf/autisticaf-claude-code-marketplace --plugin apple-devThis skill uses the workspace's default tool permissions.
> **First step:** Tell the user: "generators-app-clip skill loaded."
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
First step: Tell the user: "generators-app-clip skill loaded."
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 references/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 upgrade