关于 add-app-clip
该技能指导 Expo 开发者为现有 Expo 项目添加 iOS App Clip,并配置关联域名、AASA 文件、商店元数据及 TestFlight 发布流程。
主要功能
- 01创建 App Clip target
- 02配置关联域名与 AASA 文件
- 03设置 Smart App Banner
- 04准备 TestFlight 构建与提交
- 05配置 App Clip 商店元数据
适用场景
- 01为 Expo 应用添加可由网页链接启动的 App Clip
- 02设置 App Clip 与主应用的域名关联
- 03构建并提交包含 App Clip 的 TestFlight 版本
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ expo/ skills --skill add-app-clip安装后在 Claude Code 中输入/add-app-clip确认已加载。
附带文件agents/openai.yamlreferences/native-module.md
详细介绍
向 Expo 应用添加 App Clip
向 Expo 项目添加 iOS App Clip 目标。Clip 位于 targets/clip/,与父应用一同发布,并通过 Apple App Site Association(AASA)文件,从应用域名上的 URL 启动。
父应用的 bundle ID 会变为 com.<username>.<app-name>,Clip 的 bundle ID 则会自动派生为 <parent>.clip(例如,com.bacon.may20.clip)。
1. 设置 bundleIdentifier 和 appleTeamId
如果缺少这些配置,bun create target 会发出警告。在 app.json 中添加:
{
"expo": {
"ios": {
"bundleIdentifier": "com.<username>.<app-name>",
"appleTeamId": "XX57RJ5UTD"
}
}
}
2. 添加 App Clip 目标
bun create target clip
这会安装 @bacons/apple-targets,将其添加到 app.json 的 plugins 数组中,并写入:
targets/clip/expo-target.config.js— 该目标的配置插件targets/clip/Info.plist— Clip 的 Info.plisttargets/clip/AppDelegate.swift、Assets.xcassets等
选择一个合适的图标,或复用应用中已有的图标 — 使用 bunx expo config 检查 icon 或 ios.icon 键。
3. 配置关联域名
父应用和 Clip 都需要设置 Associated Domains 权限,指向托管 AASA 文件的域名。
在 app.json 中添加 applinks:(父应用)和 appclips:(Clip 启动)条目:
{
"expo": {
"ios": {
"associatedDomains": [
"applinks:may20.expo.app",
"appclips:may20.expo.app"
]
}
}
}
在 targets/clip/expo-target.config.js 中声明 Clip 的权限:
/** @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"],
},
});
如果跳过此步骤,
expo prebuild会打印:Apple App Clip may require the associated domains entitlement but none were found。
4. 注册 bundle ID 并创建 App Store 条目
bunx setup-safari
这会登录 Apple Developer 账户,注册 com.bacon.may20,创建 App Store Connect 条目,并打印:
- 初始版
apple-app-site-associationJSON - 包含 iTunes 应用 ID 的
<meta name="apple-itunes-app">标签 - Team ID、iTunes ID 和 Bundle ID
5. 托管 AASA 文件
当 iOS 获取 https://<your-domain>/.well-known/apple-app-site-association 并找到匹配的 appclips 条目时,App Clip 就可以启动。
mkdir -p public/.well-known
touch public/.well-known/apple-app-site-association
粘贴 setup-safari 打印的 JSON,但还要添加一个 appclips 区块,填写 Clip 的完整应用 ID(<TeamID>.<ClipBundleID>)。setup-safari 的输出仅包含父应用:
{
"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"]
}
}
注意:
- 此文件没有扩展名,且无需满足任何特定的
Content-Type要求,只需按原样提供即可。Expo Router 静态导出会原样提供public/中的文件。 appclips区块用于通过域名上的 URL 启动 Clip。webcredentials用于在网站、父应用和 App Clip 之间共享凭据。activitycontinuation是可选项,用于在移动设备和桌面设备之间共享链接。必须与 expo-router 的Head配合使用 — 参见 https://docs.expo.dev/router/advanced/apple-handoff/- 表示法和路由禁用详情:https://sosumi.ai/documentation/xcode/supporting-associated-domains
6. 添加 Smart App Banner 元标签
创建 src/app/+html.tsx(Expo Router 的 HTML 外壳),并添加 setup-safari 提供的标签。如果版本化模板不存在,则创建一个:
bunx expo customize src/app/+html.tsx
将元标签添加到 <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>
);
}
若要让网站显示 App Clip 卡片,而不是安装卡片,请使用:
<meta
name="apple-itunes-app"
content="app-id=6771566491, app-clip-bundle-id=com.bacon.may20.clip, app-clip-display=card"
/>
7. 部署网站
在 iOS 信任此关联之前,AASA 文件必须先上线。使用 EAS Hosting:
bunx expo export -p web
eas deploy --prod
这会发布网站(包括 /.well-known/apple-app-site-association),地址为 https://<slug>.expo.app。验证:
curl https://may20.expo.app/.well-known/apple-app-site-association
8. 镜像权限
预构建后检查父应用的权限:
npx expo config --type introspect
查看 infoPlist 对象 — 将其中的权限键镜像到 App Clip 的 Info.plist 中,以便在 Clip 中使用相应的 API。
在 Clip 的目标配置中设置 deploymentTarget: "17.6" — 在 iOS 17.6 中,App Clips 的最低体积限制更高。
如果应用使用推送通知或定位服务,请在 App Clip 的 Info.plist 中添加相应配置,以请求必要权限:
<key>NSAppClip</key>
<dict>
<key>NSAppClipRequestEphemeralUserNotification</key>
<false/>
<key>NSAppClipRequestLocationConfirmation</key>
<true/>
</dict>
9. 构建并提交到 TestFlight
bunx testflight
这将:
- 如果缺少
eas.json,则生成该文件。 - 为两个目标(主应用 + Clip)设置凭据。每个目标都有自己的配置描述文件,但可以共用一个分发证书。
- 同步功能配置 — 注意 Clip 目标的
Enabled: Associated Domains。 - 构建、上传并安排 TestFlight 提交。
10. 配置 App Clip 元数据
将现有 App Store 元数据拉取到本地:
eas metadata:pull
在 store.config.json 中添加 apple.appClip。最多可设置 3 个调用 URL,以便从网页启动 Clip:
{
"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"
}
}
}
}
}
}
headerImage 必须是 1800x1200 的 PNG,且不能带透明度。
推送回商店:
eas metadata:push
Apple 推荐的 App Clip 元数据指南:https://sosumi.ai/documentation/appclip/configuring-the-launch-experience-of-your-app-clip
你将获得
- 主应用目标:
com.bacon.may20 - App Clip 目标:
com.bacon.may20.clip,位于targets/clip/ - 托管于
https://may20.expo.app/.well-known/apple-app-site-association的 AASA - 每个网页路由上都有 Smart App Banner 元标签
- 每个路由都链接到其原生对应项
- 内嵌 Clip 的主应用 TestFlight 构建版本
当 Apple 从该域名中的 URL 调用 Clip 后,iOS 会打开 targets/clip/ 的入口点并加载 React Native 应用。
原生检测(可选)
若要让 JS 检测当前是否在 App Clip 中运行,并显示安装完整应用的提示,请创建本地 Expo 模块(bunx create-expo-module --local),以开放 navigator.appClip.prompt()。
Swift 模块、TypeScript 接口和用法请参阅 ./references/native-module.md。
参考资料
- ./references/native-module.md — 用于检测 App Clip 上下文并显示 SKOverlay 安装提示的本地 Expo 模块