All open-source packages
PlatformSwift

AppClipsStudio

Invocation routing, size checks and website association for iOS App Clips.

5StarsLatest Release: v2.0.0 · Updated: October 15, 2026
Platforms:iOS 16macOS 13

License: MIT

A Swift package for iOS App Clips and the apps they belong to. It validates the invocation URL the system passes at launch and routes it to your screens the way App Store Connect routes it to App Clip experiences, confirms the person is where the code is, and hands the App Clip's data to the full app. Its appclipstudio command-line tool checks each variant's size, App Clip Code URLs, the apple-app-site-association file and Associated Domains entries before you upload. No dependencies.

Features

  • Invocation routing with Apple's matching rule: patterns such as /table/:number and /shop/*, the most specific prefix wins, handlers can decline a match, and a fallback covers the rest of a registered prefix
  • Untrusted input stays bounded: https only, at most 2,048 bytes, 32 path components and 64 query items, no . or .. components, and no control or format characters in the decoded host, path or query
  • Size checks per variant: Apple's 10, 15 and 100 MB limits applied to Xcode's App Thinning Size Report.txt by iOS version, deployment target and invocation type, with an exit status for CI
  • Website association: generate and validate apple-app-site-association, check appclips: and applinks: entitlement entries, and lint App Clip Code URLs against Apple's rules
  • HandoffStore passes a versioned, expiring, size-limited Codable value to the full app through the shared App Group
  • Location confirmation with a validated region of at most 500 m, and the App Store overlay for the full app
  • An example app and App Clip (Examples/CoffeeShop) built from shared sources; CI builds it and the README samples are copied from it

Quickstart

swift
1import AppClipsStudio
2import SwiftUI
3 
4enum Screen: Equatable {
5 case welcome
6 case table(Int)
7}
8 
9struct ContentView: View {
10 @State private var screen = Screen.welcome
11 
12 var body: some View {
13 Group {
14 switch screen {
15 case .welcome: Text("Scan a table tag")
16 case .table(let number): Text("Table \(number)")
17 }
18 }
19 .font(.largeTitle)
20 .onInvocation { invocation in
21 screen = (try? Self.router.route(invocation)) ?? .welcome
22 }
23 }
24 
25 static let router: InvocationRouter<Screen> = {
26 var router = InvocationRouter<Screen>()
27 try? router.add("/table/:number") { match in
28 match.integer("number").map(Screen.table)
29 }
30 router.fallback { _ in .welcome }
31 return router
32 }()
33}

Installation

Swift Package Manager

swift
1dependencies: [
2 .package(url: "https://github.com/muhittincamdali/AppClipsStudio.git", from: "2.0.0")
3],
4targets: [
5 .target(name: "YourAppFeature", dependencies: [
6 .product(name: "AppClipsStudio", package: "AppClipsStudio")
7 ])
8]

Xcode

text
1https://github.com/muhittincamdali/AppClipsStudio.git

Command-line tool

sh
1git clone https://github.com/muhittincamdali/AppClipsStudio.git
2cd AppClipsStudio
3swift build -c release
4cp .build/release/appclipstudio /usr/local/bin/ # or run it with `swift run appclipstudio`

Screenshots

Example App Clip opened from a table tag URL: Table 12 at Harbor Street, light mode
Example App Clip opened from a table tag URL: Table 12 at Harbor Street, dark mode
Example App Clip opened from a poster URL: Flat White offer, light mode
Example App Clip opened from a poster URL: Flat White offer, dark mode

Timeline

  1. Repository opened as a modular App Clip framework

  2. v1.0.0 tagged; documentation and CI work, while the module sources stayed placeholders

  3. Cleanup: the modules were consolidated into a single target of a few stubs

  4. Rebuilt as 2.0.0 from Apple's App Clip documentation: invocation routing, size checks, website association and the appclipstudio CLI; no 1.0.0 API kept

Links

Related Article

Read the article