add-app-clip
关于
This skill adds an iOS App Clip target to an Expo project, enabling a lightweight app experience invoked from URLs. It automatically configures the Clip with a derived bundle identifier and sets up the required Apple App Site Association (AASA) file. Use it when users need to implement App Clips, smart app banners, or URL-invoked iOS app slices alongside their main application.
快速安装
Claude Code
推荐npx skills add expo/skills -a claude-code/plugin add https://github.com/expo/skillsgit clone https://github.com/expo/skills.git ~/.claude/skills/add-app-clip在 Claude Code 中复制并粘贴此命令以安装该技能
技能文档
Add an App Clip to an Expo App
Adds an iOS App Clip target to an Expo project. The Clip lives in targets/clip/, ships alongside the parent app, and is invoked from a URL on the app's domain via an Apple App Site Association (AASA) file.
The parent app's bundle ID becomes com.<username>.<app-name> and the Clip's is automatically derived as <parent>.clip (e.g. com.bacon.may20.clip).
1. Set bundleIdentifier and appleTeamId
bun create target warns if these are missing. Add to app.json:
{
"expo": {
"ios": {
"bundleIdentifier": "com.<username>.<app-name>",
"appleTeamId": "XX57RJ5UTD"
}
}
}
2. Add the App Clip target
bun create target clip
This installs @bacons/apple-targets, adds it to the plugins array in app.json, and writes:
targets/clip/expo-target.config.js— the target's config plugintargets/clip/Info.plist— Clip Info.plisttargets/clip/AppDelegate.swift,Assets.xcassets, etc.
Pick a good icon or reuse the existing one defined in the app — check it with bunx expo config under the icon or ios.icon key.
3. Wire up associated domains
The parent app and the Clip each need the Associated Domains entitlement pointing at the domain that hosts the AASA file.
In app.json, add both applinks: (parent) and appclips: (Clip invocation) entries:
{
"expo": {
"ios": {
"associatedDomains": [
"applinks:may20.expo.app",
"appclips:may20.expo.app"
]
}
}
}
In targets/clip/expo-target.config.js, declare the Clip's entitlement:
/** @type {import('@bacons/apple-targets/app.plugin').ConfigFunction} */
module.exports = (config) => ({
type: "clip",
icon: "https://github.com/expo.png",
entitlements: {
"com.apple.developer.associated-domains": ["appclips:may20.expo.app"],
},
});
If you skip this,
expo prebuildwill print:Apple App Clip may require the associated domains entitlement but none were found.
4. Register bundle IDs and create the App Store entry
bunx setup-safari
This logs in to the Apple Developer account, registers com.bacon.may20, creates the App Store Connect entry, and prints:
- A starter
apple-app-site-associationJSON - A
<meta name="apple-itunes-app">tag with the iTunes app id - Team ID, iTunes ID, and Bundle ID
5. Host the AASA file
App Clips are invoked when iOS fetches https://<your-domain>/.well-known/apple-app-site-association and finds a matching appclips entry.
mkdir -p public/.well-known
touch public/.well-known/apple-app-site-association
Paste the JSON setup-safari printed, but add an appclips block for the Clip's full app ID (<TeamID>.<ClipBundleID>). The output of setup-safari only covers the parent app:
{
"applinks": {
"details": [
{
"appIDs": ["XX57RJ5UTD.com.bacon.may20"],
"components": [{ "/": "*", "comment": "Matches all routes" }]
}
]
},
"appclips": {
"apps": ["XX57RJ5UTD.com.bacon.may20.clip"]
},
"activitycontinuation": {
"apps": ["XX57RJ5UTD.com.bacon.may20"]
},
"webcredentials": {
"apps": ["XX57RJ5UTD.com.bacon.may20"]
}
}
Notes:
- The file has no extension and no
Content-Typerequirements beyond being served as-is. Expo Router static export serves files inpublic/verbatim. - The
appclipsblock is what lets a URL on the domain launch the Clip. webcredentialsis used for sharing credentials between the website, parent app, and the App Clip.activitycontinuationis optional and used for sharing the link between mobile and desktop. Must be used withHeadfrom expo-router — see https://docs.expo.dev/router/advanced/apple-handoff/- Notation and route-disabling details: https://sosumi.ai/documentation/xcode/supporting-associated-domains
6. Add the Smart App Banner meta tag
Create src/app/+html.tsx (Expo Router's HTML shell) and add the tag from setup-safari. Create the versioned template if it doesn't exist:
bunx expo customize src/app/+html.tsx
Add the meta tag to the <head>:
import { ScrollViewStyleReset } from "expo-router/html";
export default function Root({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="apple-itunes-app" content="app-id=6771566491" />
<ScrollViewStyleReset />
</head>
<body>{children}</body>
</html>
);
}
To make the website show the App Clip card instead of the install card, use:
<meta
name="apple-itunes-app"
content="app-id=6771566491, app-clip-bundle-id=com.bacon.may20.clip, app-clip-display=card"
/>
7. Deploy the website
The AASA file must be live before iOS will trust the association. Use EAS Hosting:
bunx expo export -p web
eas deploy --prod
This publishes the site (including /.well-known/apple-app-site-association) at https://<slug>.expo.app. Verify:
curl https://may20.expo.app/.well-known/apple-app-site-association
8. Mirror permissions
Inspect the parent app's permissions after prebuild:
npx expo config --type introspect
Look at the infoPlist object — mirror the permission keys in the App Clip's Info.plist so matching APIs can be used from the Clip.
Set deploymentTarget: "17.6" in the Clip's target config — App Clips have a higher minimum size limit in iOS 17.6.
If the app uses push notifications or location services, add to the App Clip's Info.plist to request the necessary permissions:
<key>NSAppClip</key>
<dict>
<key>NSAppClipRequestEphemeralUserNotification</key>
<false/>
<key>NSAppClipRequestLocationConfirmation</key>
<true/>
</dict>
9. Build and submit to TestFlight
bunx testflight
This will:
- Generate an
eas.jsonif missing. - Set up credentials for both targets (parent + Clip). Each gets its own provisioning profile but can share a single Distribution Certificate.
- Sync capabilities — note
Enabled: Associated Domainsfor the Clip target. - Build, upload, and schedule a TestFlight submission.
10. Configure App Clip metadata
Pull existing App Store metadata to local:
eas metadata:pull
Add apple.appClip to store.config.json. Up to 3 invocation URLs can launch the Clip from a web page:
{
"configVersion": 0,
"apple": {
"appClip": {
"defaultExperience": {
"action": "PLAY",
"releaseWithAppStoreVersion": true,
"reviewDetail": {
"invocationUrls": ["https://may20.expo.app/", null, null]
},
"info": {
"en-US": {
"subtitle": "Instantly native with Expo",
"headerImage": "store/apple/app-clip/en-US/asc-app-clip.png"
}
}
}
}
}
}
The headerImage must be a 1800x1200 PNG with no opacity.
Push back to the store:
eas metadata:push
Apple's recommended App Clip metadata guidelines: https://sosumi.ai/documentation/appclip/configuring-the-launch-experience-of-your-app-clip
What you get
- Parent app target:
com.bacon.may20 - App Clip target:
com.bacon.may20.clip, lives intargets/clip/ - AASA hosted at
https://may20.expo.app/.well-known/apple-app-site-association - Smart App Banner meta tag on every web route
- Every route linked to its native counterpart
- TestFlight build of the parent app with the Clip embedded
Once Apple invokes the Clip from a URL on the domain, iOS opens targets/clip/'s entry point which loads the React Native app.
Native detection (optional)
To let JS detect when it's running inside an App Clip and present an install prompt for the full app, create a local Expo module (bunx create-expo-module --local) that exposes navigator.appClip.prompt().
See ./references/native-module.md for the Swift module, TypeScript interface, and usage.
References
- ./references/native-module.md — Local Expo module to detect App Clip context and present the SKOverlay install prompt
GitHub 仓库
相关推荐技能
executing-plans
设计该Skill用于当开发者提供完整实施计划时,以受控批次方式执行代码实现。它会先审阅计划并提出疑问,然后分批次执行任务(默认每批3个任务),并在批次间暂停等待审查。关键特性包括分批次执行、内置检查点和架构师审查机制,确保复杂系统实现的可控性。
requesting-code-review
设计该Skill可在完成任务、实现主要功能或合并代码前自动调度代码审查子代理,确保实现符合需求和计划。它支持通过指定git SHA范围进行精准的代码变更审查,帮助开发者在关键节点及时发现潜在问题。核心原则是"早审查、勤审查",适用于开发流程的各个关键阶段。
connect-mcp-server
设计这个Skill指导开发者如何将MCP服务器连接到Claude Code,支持HTTP、stdio和SSE三种传输协议。它涵盖了从安装配置到认证安全的完整流程,适用于集成GitHub、Notion、数据库等外部服务。当开发者需要添加集成、配置外部工具或提及MCP相关功能时,这个Skill能提供实用的操作指南。
web-cli-teleport
设计该Skill帮助开发者根据任务特性选择Claude Code的Web或CLI界面,并指导如何在两种环境间无缝迁移会话。它能分析任务复杂度、迭代需求等要素,推荐最优工作界面和工作流。关键特性包括会话状态管理、环境切换指导和上下文优化建议。
