Claude
Skills
Sign in
Back

apple-appclip

Included with Lifetime
$97 forever

Use this skill whenever the user wants to create, configure, implement, debug, or learn about Apple App Clips for iOS apps. Triggers include: any mention of 'App Clip', 'app clip', 'App Clip Code', 'invocation URL', 'App Clip experience', lightweight app, instant app experience, or demo version of an iOS app. Also use when the user asks about sharing data between an App Clip and a full app, configuring App Clip experiences in App Store Connect, App Clip size limits, responding to invocations, Smart App Banners for App Clips, NFC-integrated codes, or App Clip to full app transitions. Use this skill even if the user just mentions wanting a "lightweight version" or "instant experience" for their iOS app — they likely need an App Clip. Do NOT use for general iOS development unrelated to App Clips, Android Instant Apps, or Progressive Web Apps.

Code Review

What this skill does


# Apple App Clip Skill

Guide users through creating, configuring, and implementing Apple App Clips — lightweight versions
of iOS apps that provide instant, in-the-moment experiences or demo versions.

For the full Apple developer documentation reference, read:
`references/apple-appclip-full-docs.md`

---

## What is an App Clip?

An App Clip is a lightweight version of an iOS app that offers some of its functionality instantly —
without requiring installation from the App Store. App Clips are designed for:

- **In-the-moment experiences**: Order food, pay for parking, rent a scooter — fast, focused tasks
- **Demo versions**: Let users try a game level, a workout, or a feature before buying/subscribing

App Clips don't appear on the Home Screen and are removed by the system after a period of inactivity.

---

## Size Limits

| iOS Version        | Max Uncompressed App Clip Binary |
|--------------------|----------------------------------|
| iOS 15 and earlier | 10 MB                            |
| iOS 16 and earlier | 15 MB                            |
| iOS 17 and later   | 100 MB (with restrictions below) |

The 100 MB limit on iOS 17+ requires:
- Only digital invocations (website, Spotlight) — no physical invocations (NFC, QR, App Clip Codes)
- Reliable internet expected
- No iOS 16 or earlier support
- Exception: The App Clip demo link from App Store Connect allows 100 MB AND physical invocations

Use Background Assets framework to download additional content (but not with `isEssential` priority).

---

## Xcode Project Setup

### Add an App Clip Target

1. Open your existing iOS project (or create a new one)
2. Add a new target using the **App Clip** template
3. Choose product name and options, click Finish

Xcode automatically creates:
- A scheme to build/run the App Clip
- The `On Demand Install Capable` capability (`com.apple.developer.on-demand-install-capable`)
- The `Parent Application Identifiers Entitlement`
- An app identifier: `$(AppIdentifierPrefix)com.example.MyApp.Clip`
- The `_XCAppClipURL` environment variable for debugging invocations

### Share Code Between App Clip and Full App

- Use Swift packages for shared components
- Share asset catalogs between targets
- Use Active Compilation Conditions for conditional code:

```swift
#if !APPCLIP
// Code only for full app
#else
// Code for App Clip
#endif
```

Add `APPCLIP` to the App Clip target's Active Compilation Conditions build setting.

### Verify Size

1. Archive the app in Xcode
2. Export as Ad Hoc/Development with App Thinning enabled
3. Check `App Thinning Size Report.txt` for uncompressed sizes per variant

---

## Invocations & Launch Experience

### How Users Discover App Clips

- **App Clip Codes** (NFC-integrated or scan-only)
- **QR codes** and **NFC tags**
- **Safari Smart App Banners**
- **Links in Messages**
- **Maps** and **Spotlight search**
- **Location-based Siri suggestions**
- **Other apps** (via App Clip links)

### Invocation URLs

Invocation URLs identify which experience to show. Configure them in App Store Connect:

- **Default App Clip experience**: Basic experience with auto-generated App Clip link
- **Demo link**: Generated by App Store Connect, supports 100 MB size limit
- **Advanced App Clip experiences**: Custom URLs with prefix matching

Example URL structure:
```
https://example.com/location1
https://example.com/location2
https://appclip.example.com/shop?p=123
```

Both the App Clip AND the full app must handle all registered invocation URLs.

### Responding to Invocations in Code

**SwiftUI lifecycle:**
```swift
@main
struct MyAppClip: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { activity in
                    respondTo(activity)
                }
        }
    }
}
```

**Scene-based lifecycle:**
Implement `scene(_:willConnectTo:options:)` for first launch and
`scene(_:willContinueUserActivityWithType:)` for subsequent invocations.

**Extract the URL:**
```swift
func respondTo(_ activity: NSUserActivity?) {
    guard let activity, activity.activityType == NSUserActivityTypeBrowsingWeb else { return }
    let incomingURL = activity.webpageURL
    guard let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else { return }
    // Update UI based on URL components
}
```

Important: If you register a generic URL like `https://example.com/`, your code must handle that
URL even if you only intend to use it as a prefix for more specific invocations.

---

## App Clip Experiences Configuration

### Default Experience
- Created automatically in App Store Connect
- Uses the auto-generated App Clip link or a custom URL

### Demo Link
- Generated by App Store Connect
- Allows 100 MB App Clips with physical invocations
- No launch parameters supported

### Advanced Experiences
- Custom invocation URLs with prefix matching
- Required for App Clip Codes
- Must associate App Clip with your website (AASA file)
- Supports location-based experiences

---

## App Clip Codes

### Types
- **NFC-integrated**: Users hold device near the code OR scan it
- **Scan-only**: Users scan with Camera app or Code Scanner

### Creation Tools
- **App Store Connect**: Visual interface, instant preview
- **App Clip Code Generator CLI**: Scriptable, works without ASC experience

CLI example:
```bash
AppClipCodeGenerator generate \
  --url https://example.com/shop \
  --index 0 \
  --output ~/Downloads/AppClipCode.svg \
  --logo badge
```

### URL Encoding Best Practices
- Use short hostnames, few subdomains
- Remove `www` subdomain
- Use `appclip` as first subdomain for efficient encoding: `https://appclip.example.com`
- Use short query parameter names: `?p=0` not `?status=view`
- Use decimal numbers for values
- Omit trailing slashes
- Avoid long UUIDs
- Use single-word path components from Apple's optimized list (see reference docs)

Valid URL characters:
- Host: lowercase `a-z`, `.`, `-`
- Path/query: `a-z`, `A-Z`, `0-9`, `/#?=%-._,+;:&`

---

## Website Association (AASA)

Required for advanced App Clip experiences and iOS 16.3 or earlier invocations.

### Server-Side Setup

Add to `https://yourdomain.com/.well-known/apple-app-site-association`:

```json
{
    "appclips": {
        "apps": ["ABCDE12345.com.example.MyApp.Clip"]
    }
}
```

Requirements:
- Serve from `/.well-known/` path directly (no redirects)
- Content-Type: `application/json`
- Valid HTTPS with trusted certificate
- File size ≤ 128 KB

### Smart App Banner

Add to your website's `<head>`:
```html
<meta name="apple-itunes-app" content="app-id=myAppStoreID, app-clip-bundle-id=com.example.MyApp.Clip, app-clip-display=card">
```

---

## Data Sharing: App Clip → Full App

### Shared App Group Container
```swift
// In both App Clip and full app
let sharedDefaults = UserDefaults(suiteName: "group.com.example.myapp")
sharedDefaults?.set("someValue", forKey: "someKey")
```

### Keychain (for sensitive data)
```swift
// App Clip stores:
let addQuery: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecValueData as String: "secret-token".data(using: .utf8)!,
    kSecAttrLabel as String: "my-appclip"
]
SecItemAdd(addQuery as CFDictionary, nil)

// Full app reads:
var readQuery: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecReturnAttributes as String: true,
    kSecAttrLabel as String: "my-appclip",
    kSecReturnData as String: true
]
var result: AnyObject?
SecItemCopyMatching(readQuery as CFDictionary, &result)
```

### Sign in with Apple
Store credentials in shared UserDefaults so the full app can sign in automatically:
```swift
let groupDefaults = UserDefaults(suiteName: "group.com.example.myapp")
guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else { return }
groupDefaults?.set(credential.user, forKey: "SavedUserID")
```

### CloudKit (iOS 16+)
App Clips can read public iCloud database only
Files: 2
Size: 226.4 KB
Complexity: 49/100
Category: Code Review

Related in Code Review