Complete guide for building beautiful apps with Expo Router. Covers fundamentals, styling, components, navigation, animations, patterns, and native tabs.
日本語の概要は準備中です。原文の説明を表示しています。
Prepare and submit NowStack Mobile iOS App Store releases. Use for real 6.5-inch app screenshots, metadata, IAP, review details, validation, and submit.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Take a TestFlight-ready app all the way to App Store review submission: store screenshots, metadata, IAP pricing/availability, age rating, review details with demo account, validation, and submit. If no build is on TestFlight yet, run ns-ios-testflight first.
Everything runs with repo tools and public CLIs only:
mobile-app/scripts/asc-api.mjs for all App Store Connect API calls (ASC_KEY_ID/ASC_ISSUER_ID/ASC_P8_PATH env vars).asc CLI for uploads (screenshots, subscription assets) and validation.mobile-app/scripts/store-screenshots.mjs + Maestro + xcrun simctl for captures.Sequencing with the rest of the lifecycle:
ns-ios-testflight skill first..agents/skills/ns-generate-store-screenshots/SKILL.md..agents/skills/ns-ios-deploy-app/SKILL.md / .agents/skills/ns-deploy-android-app/SKILL.md.
</objective>
<state_variables>
| Variable | Source |
|---|---|
{asc_app_id} | GET /v1/apps?filter[bundleId]={bundle_id} |
{version_id} | the appStoreVersions id in PREPARE_FOR_SUBMISSION |
{version_loc_id} | en-US appStoreVersionLocalizations id |
{app_info_id} / {app_info_loc_id} | from GET /v1/apps/{asc_app_id}/appInfos (+ its localizations) |
{build_db_id} | processed build id from GET /v1/builds?filter[app]={asc_app_id} |
{subscription_id} / {sub_group_id} | if the app sells a subscription |
{screenshots_dir} | dated output of the screenshot run, e.g. documents/store-screenshots/<date>/ios/iphone-65/en-US |
| </state_variables> |
<critical_safety>
documents/store-screenshots/ is gitignored — keep it that way./store/*, store/[shot], or any other fake screenshot route, stop and remove/ignore it before capturing or uploading App Store screenshots.site-config.ts — do not invent them.
</critical_safety><asc_entity_map> App Store Connect data model — knowing which entity owns which field saves hours:
| Field | Entity | Endpoint |
|---|---|---|
| description, keywords, promotionalText, supportUrl, marketingUrl | appStoreVersionLocalizations | PATCH /v1/appStoreVersionLocalizations/{id} |
| subtitle, privacyPolicyUrl | appInfoLocalizations | PATCH /v1/appInfoLocalizations/{id} |
| primaryCategory | appInfos | PATCH /v1/appInfos/{id} (relationships) |
| copyright, release type | appStoreVersions | PATCH /v1/appStoreVersions/{id} |
| attached build | appStoreVersions relationship | PATCH /v1/appStoreVersions/{id}/relationships/build |
| age rating answers | ageRatingDeclarations | PATCH /v1/ageRatingDeclarations/{id} |
| contact + demo account | appStoreReviewDetails | POST /v1/appStoreReviewDetails |
| content rights | apps | asc apps update --id {asc_app_id} --content-rights ... |
| </asc_entity_map> |
ns-ios-testflight skill first.{version_id}: GET /v1/apps/{asc_app_id}/appStoreVersions?filter[appStoreState]=PREPARE_FOR_SUBMISSION. If none exists, create it: POST /v1/appStoreVersions with {platform: "IOS", versionString: "<version>"} + app relationship.site-config.ts: urls (website/privacy/terms), support email, payment product IDs, price.docs/production-checklist.md stage 2.
</phase>
convex/seedStoreDemo.ts, app-specific) so real screens show clean demo content. Sign in with the built-in review account appstoretest@email.com / OTP 123456 for auth-gated screens. Never use real personal data.EXPO_PUBLIC_ALLOW_DEV_PAYMENT_BYPASS=false so the real paywall renders (restore afterwards). The paywall screenshot must be the actual in-app paywall, not a recreated promo screen.IPHONE_65. Do not use iPhone 14 Plus / iPhone 15 Pro Max / 6.7-inch screenshots unless the user explicitly asks for another slot.xcrun simctl create "store-iphone-65" "com.apple.CoreSimulator.SimDeviceType.iPhone-11-Pro-Max" <runtime>
cd mobile-app && npm run screenshots:store:ios # dry-run first, always
npm run screenshots:store:ios -- --execute # after user confirms
mobile-app/maestro/store/ (Maestro needs JDK 17: export JAVA_HOME=/opt/homebrew/opt/openjdk@17). Robust flow patterns: extendedWaitUntil: {visible: "<text>", timeout: 10000} before every tap; conditional paywall dismissal with runFlow: when: visible:.sips -g pixelWidth -g pixelHeight *.png — every file must be exactly 1242x2688. Then visual QA each PNG (read the images): real app screen, no fake route, no dev overlays, no status-bar clutter, no placeholder copy, no invented claims.
</phase>
Write metadata (draft it from docs/templates/app-store-metadata.example.json + site-config.ts, show the user for approval first):
PATCH /v1/appStoreVersionLocalizations/{version_loc_id} — description (append Terms of Use: <terms-url> and Privacy Policy: <privacy-url> at the end — Apple requires visible terms for subscription apps), keywords (100 chars max, comma-separated, no spaces after commas), promotionalText, supportUrl, marketingUrl.PATCH /v1/appInfoLocalizations/{app_info_loc_id} — subtitle (30 chars max), privacyPolicyUrl.PATCH /v1/appInfos/{app_info_id} — primaryCategory relationship (e.g. {"type":"appCategories","id":"LIFESTYLE"}).PATCH /v1/appStoreVersions/{version_id} — copyright (<year> <company name>).Upload screenshots:
asc screenshots upload --version-localization "{version_loc_id}" \
--path "{screenshots_dir}" --device-type "IPHONE_65"
</phase>
<phase n="D" title="IAP / subscription readiness" optional="skip if the app sells nothing on iOS">
The product/subscription must exist in App Store Connect with the EXACT id from `site-config.ts > payment.productIds.apple`.
# names + descriptions testers/reviewers see
asc subscriptions groups localizations create --group {sub_group_id} --locale en-US --name "<group display name>"
asc subscriptions localizations create --subscription-id {subscription_id} --app {asc_app_id} \
--locale en-US --name "<plan name>" --description "<one-line benefit>"
# pricing: set one base price, propagate everywhere
asc subscriptions pricing equalize --subscription-id {subscription_id} \
--base-price "<price>" --base-territory "<ISO3>" --confirm
# availability: if "app availability not found", initialize via the v2 API with ALL territory ids
node mobile-app/scripts/asc-api.mjs GET "/v1/territories?limit=200" # collect ids
# POST /v2/appAvailabilities with app relationship + territoryAvailabilities for every territory
# review screenshot for the subscription/IAP (use the real in-app paywall capture)
asc subscriptions review screenshots create --subscription-id {subscription_id} \
--file "{screenshots_dir}/<paywall>.png"
Target state: subscription shows READY_TO_SUBMIT. If a screenshot asset gets stuck in processing, delete it and re-upload.
</phase>
node mobile-app/scripts/asc-api.mjs GET "/v1/appInfos/{app_info_id}/ageRatingDeclaration" node mobile-app/scripts/asc-api.mjs PATCH /v1/ageRatingDeclarations/<id> /tmp/age-req.json
- **Export compliance**: add `"ITSAppUsesNonExemptEncryption": false` to `infoPlist` in `mobile-app/app.config.ts` (standard HTTPS-only apps) so every build auto-answers it.
- **App Privacy questionnaire is WEB-ONLY** — the API cannot complete it. Give the user the direct link `https://appstoreconnect.apple.com/apps/{asc_app_id}/distribution/privacy` plus the exact declarations to click, derived from what the app actually collects (this boilerplate baseline: email + user content, linked to identity, no tracking). This is the one manual gate before submission.
</phase>
<phase n="F" title="Review details, validate, submit">
```bash
# review details — the demo account is built into the boilerplate auth
node mobile-app/scripts/asc-api.mjs POST /v1/appStoreReviewDetails /tmp/review-req.json
review-req.json: contact name/email/phone from the user, demoAccountName: "appstoretest@email.com", demoAccountPassword: "123456", demoAccountRequired: true, and notes explaining the OTP flow: "Sign in with the email OTP flow: enter appstoretest@email.com, the one-time code is fixed to 123456 for this account." Describe the core flow in 2-3 sentences.
asc validate --app {asc_app_id} --version "<version>" --platform IOS --output json
Fix every severity: error (the phases above cover all standard ones). When clean AND the user confirms App Privacy is published:
asc review submit --app {asc_app_id} --version "<version>" --dry-run --output table
asc review submit --app {asc_app_id} --version "<version>" --confirm # only after explicit user confirmation
Report: version, build number, what was submitted, expected review timeline, and how to monitor (asc status --app {asc_app_id}).
</phase>
<failure_modes>
asc validate error: missing screenshots → wrong display type or wrong dimensions. App Store "iPhone 6.5 Display" = IPHONE_65; screenshots must be exactly 1242x2688./store route, marketing card, or invented overlay copy → discard the set. Capture the real app screens only, with demo data if needed.pricing availability edit: app availability not found → availability was never initialized; use POST /v2/appAvailabilities (v2!) with all territories, then retry.EXPO_PUBLIC_ALLOW_DEV_PAYMENT_BYPASS was true during capture; set it false, relaunch, recapture.eraseText: 50 then inputText), keep one input per flow step.docs/troubleshooting.md).<success_metrics>
IPHONE_65 display type.READY_TO_SUBMIT with localized name, price, availability, and review screenshot.asc validate returns zero errors.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Complete guide for building beautiful apps with Expo Router. Covers fundamentals, styling, components, navigation, animations, patterns, and native tabs.
日本語の概要は準備中です。原文の説明を表示しています。
Routes general Convex requests to the right project skill. Use when the user asks which Convex skill to use or gives an underspecified Convex app task.
日本語の概要は準備中です。原文の説明を表示しています。
Use when optimizing Convex database read bandwidth, documents-read cost, query indexes, full-table scans, function-level usage dashboard findings, or code that uses .filter(), unbounded .collect(), N+1 reads, or expensive reactive Convex queries.
日本語の概要は準備中です。原文の説明を表示しています。
Build reusable Convex components with isolated tables and app-facing wrappers. Use for defineComponent, app.use, ComponentApi, or shared backend modules.
日本語の概要は準備中です。原文の説明を表示しています。
Plan safe Convex schema and data migrations. Use for widen-migrate-narrow rollouts, backfills, breaking field changes, table splits, or failed schema deploys.
日本語の概要は準備中です。原文の説明を表示しています。
Audit Convex performance for hot reads, write contention, subscriptions, function limits, OCC conflicts, latency, read amplification, and expensive reactive queries.
日本語の概要は準備中です。原文の説明を表示しています。