HANDOFF VITTO MOBILE STORE SUBMISSION

Documentation for Sessions

Vitto Mobile — App Store & Google Play Submission Handoff

Session: 148 | From: Claude Code (coding agent) | To: Cowork agent (testing director) Date: 2026-02-26 | Priority: High Branch: session-148


Executive Summary

Session 148 completed the full Capacitor mobile app implementation. The app builds, native iOS/Android projects are generated, auth flow works, CI/CD pipeline is ready. What remains is manual store setup — creating certificates, provisioning profiles, store listings, and GitHub secrets that cannot be automated. This handoff provides step-by-step instructions with verification checkpoints.


What Was Completed (Session 148)

Item Status Verification
Capacitor 8 packages installed DONE yarn list @capacitor/core shows ^8.1.0
iOS native project generated DONE apps/vitto-mobile/ios/ exists with Xcode workspace
Android native project generated DONE apps/vitto-mobile/android/ exists with Gradle project
CapacitorBridgeService auth flow fixed DONE desktop-welcome.component.ts handles both Tauri + Capacitor
Deep link scheme unified to vitto:// DONE Info.plist + AndroidManifest.xml both register vitto scheme
Safe-area/notch CSS handling DONE viewport-fit=cover in index.html, CSS vars in styles.scss
App icons generated (97 assets) DONE @capacitor/assets generate from 1024x1024 source
CI/CD workflow created DONE .github/workflows/release-vitto-mobile.yml
Release script created DONE tools/scripts/release/release-vitto-mobile.js (5-file version sync)
Signing setup documentation DONE deployment/docs/VITTO-MOBILE-SIGNING-SETUP.md
Release workflow documentation DONE deployment/docs/VITTO-MOBILE-RELEASE.md

What Remains (This Handoff)

Phase A: Apple Developer Portal Setup

Phase B: App Store Connect Setup

Phase C: Android Keystore & Play Console Setup

Phase D: GitHub Secrets Configuration

Phase E: First Test Build Verification

Phase F: First Store Submission


Phase A: Apple Developer Portal Setup

Where: https://developer.apple.com/account

A1. Create Apple Distribution Certificate

The existing APPLE_CERTIFICATE from Tauri desktop is a "Developer ID Application" certificate — this is for macOS distribution outside the App Store. For iOS App Store, you need an Apple Distribution certificate (different type, same account).

Steps:

  1. Go to Certificates, Identifiers & Profiles > Certificates
  2. Click (+) > Select Apple Distribution
  3. Create a Certificate Signing Request (CSR):
    • Open Keychain Access > Certificate Assistant > Request a Certificate from a CA
    • Enter your email, select "Saved to disk"
  4. Upload the CSR, download the .cer file
  5. Double-click the .cer to install it in Keychain
  6. In Keychain Access, find the certificate under "My Certificates"
  7. Right-click > Export as .p12 (set a strong password, write it down)

Verification:

# Check that the certificate is installed:
security find-identity -v -p codesigning | grep "Apple Distribution"
# Should show: Apple Distribution: GoGrab LLC (SFG3Z4GLEB)

Encode for GitHub:

base64 -i vitto-ios-dist.p12 | tr -d '\n' | pbcopy
# Clipboard now contains the base64-encoded certificate

CRITICAL: Do NOT use base64 -i then pipe into another base64 -i. That double-encodes. Same lesson learned from Session 141.7 with Tauri signing key.

A2. Register App ID

  1. Go to Identifiers > (+)
  2. Select App IDs > Continue
  3. Platform: iOS
  4. Description: Vitto Mobile
  5. Bundle ID: Explicit > space.gograb.vitto.mobile
  6. Capabilities: Check Push Notifications
  7. Optionally check Associated Domains (for future Universal Links)
  8. Click Continue > Register

Verification: The App ID space.gograb.vitto.mobile appears in the Identifiers list.

A3. Create App Store Provisioning Profile

  1. Go to Profiles > (+)
  2. Select App Store Connect under Distribution
  3. Select App ID: space.gograb.vitto.mobile
  4. Select Certificate: the Apple Distribution certificate from step A1
  5. Name it: Vitto Mobile App Store
  6. Download the .mobileprovision file

Encode for GitHub:

base64 -i "Vitto_Mobile_App_Store.mobileprovision" | tr -d '\n' | pbcopy

Verification:

# Check profile details:
security cms -D -i "Vitto_Mobile_App_Store.mobileprovision" | grep -A1 "TeamIdentifier"
# Should show: SFG3Z4GLEB

Phase B: App Store Connect Setup

Where: https://appstoreconnect.apple.com

B1. Create App Store Connect API Key

  1. Go to Users and Access > Integrations > App Store Connect API
  2. Click (+) to generate a new API key
  3. Name: Vitto GitHub Actions
  4. Access: App Manager (minimum role for TestFlight upload)
  5. IMMEDIATELY download the .p8 file — this is a one-time download, Apple will not let you download it again
  6. Note the Key ID (shown on the page, e.g., XXXXXXXXXX)
  7. Note the Issuer ID (shown at the top of the API Keys page)

Encode for GitHub:

base64 -i "AuthKey_XXXXXXXXXX.p8" | tr -d '\n' | pbcopy

Save these three values:

B2. Create the App in App Store Connect

  1. Go to My Apps > (+) > New App
  2. Platform: iOS
  3. Name: Vitto
  4. Primary Language: English (U.S.)
  5. Bundle ID: select space.gograb.vitto.mobile (registered in step A2)
  6. SKU: vitto-mobile
  7. User Access: Full Access

B3. Fill Required App Information

Under App Information:

Under App Privacy:

Under Pricing and Availability:

B4. Prepare Screenshots

Required minimum sizes:

Take screenshots from iOS Simulator:

# Run the app on iPhone 15 Pro Max simulator
cd apps/vitto-mobile && npx cap run ios --target "iPhone 15 Pro Max"
# In Simulator: Cmd+S to take screenshot

Recommended screenshots (3-5):

  1. Welcome/Sign-in screen
  2. Main dashboard after login
  3. AI chat conversation
  4. Settings or profile view

B5. App Review Information

Verification: App status shows "Prepare for Submission" (yellow).


Phase C: Android Setup

C1. Generate Upload Keystore

keytool -genkey -v \
  -keystore ~/.android/vitto-upload.jks \
  -keyalg RSA -keysize 2048 \
  -validity 10000 \
  -alias vitto-upload \
  -storepass "<CHOOSE_PASSWORD>" \
  -keypass "<CHOOSE_KEY_PASSWORD>" \
  -dname "CN=GoGrab LLC, OU=Mobile, O=GoGrab LLC, L=City, ST=State, C=US"

Encode for GitHub:

base64 -i ~/.android/vitto-upload.jks | tr -d '\n' | pbcopy

Save these four values:

IMPORTANT: Back up ~/.android/vitto-upload.jks securely. With Google Play App Signing, this is your upload key. Google can reset it if lost, but it's painful.

C2. Create Google Play Developer Account

If not already created:

  1. Go to https://play.google.com/console/signup
  2. Pay $25 one-time registration fee
  3. Complete identity verification (can take 48 hours for organizations)

Verification: You can access https://play.google.com/console/

C3. Create App in Google Play Console

  1. Go to All apps > Create app
  2. App name: Vitto - AI Assistant
  3. Default language: English (United States)
  4. App or game: App
  5. Free or paid: Free
  6. Declarations: Accept all

C4. First Manual AAB Upload

Google Play requires the first .aab to be uploaded manually before automated CI/CD can push subsequent builds.

# Build the Angular app
cd /Users/fguijarro/developer/repos-gspace/gspace1
yarn nx build app-gograb-ai --configuration=production

# Sync to Android project
cd apps/vitto-mobile && npx cap sync android

# Build the .aab
cd android && ./gradlew bundleRelease

The .aab will be at:

apps/vitto-mobile/android/app/build/outputs/bundle/release/app-release.aab

Upload it:

  1. Google Play Console > your app > Testing > Internal testing
  2. Create new release
  3. Upload app-release.aab
  4. Add release notes: "Initial internal test build"
  5. Review and start rollout

Verification: The Internal testing track shows "Available to internal testers".

C5. Create Google Play Service Account

  1. Go to Google Cloud Console (https://console.cloud.google.com)
  2. Select/create a project for GoGrab
  3. IAM & Admin > Service Accounts > Create Service Account
  4. Name: vitto-github-deploy
  5. Role: Service Account User
  6. Click Create and Continue
  7. Under the new service account: Keys > Add Key > Create New Key > JSON
  8. Download the JSON key file

Link to Play Console:

  1. Google Play Console > Settings > API access
  2. Link the Google Cloud project
  3. Find vitto-github-deploy in the service accounts list
  4. Grant permissions: Release to production (or at minimum "Manage testing tracks")

Encode for GitHub:

base64 -i service-account-key.json | tr -d '\n' | pbcopy

Verification: In Google Play Console > API access, the service account shows "Access granted".


Phase D: GitHub Secrets Configuration

Where: GitHub repo > Settings > Secrets and variables > Actions

Secret Checklist (13 total)

# Secret Name Source Value From
1 APPLE_TEAM_ID Already exists SFG3Z4GLEB (reused from desktop)
2 IOS_DISTRIBUTION_CERTIFICATE_BASE64 Step A1 Base64 .p12
3 IOS_DISTRIBUTION_CERTIFICATE_PASSWORD Step A1 .p12 export password
4 IOS_PROVISIONING_PROFILE_BASE64 Step A3 Base64 .mobileprovision
5 IOS_PROVISIONING_PROFILE_NAME Step A3 Vitto Mobile App Store
6 APPSTORE_API_KEY_ID Step B1 Key ID from ASC
7 APPSTORE_API_ISSUER_ID Step B1 Issuer ID from ASC
8 APPSTORE_API_KEY_BASE64 Step B1 Base64 .p8
9 ANDROID_KEYSTORE_BASE64 Step C1 Base64 .jks
10 ANDROID_KEYSTORE_PASSWORD Step C1 Keystore password
11 ANDROID_KEY_ALIAS Step C1 vitto-upload
12 ANDROID_KEY_PASSWORD Step C1 Key password
13 GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_BASE64 Step C5 Base64 JSON

Verification:

# List all mobile-related secrets (names only, not values):
gh secret list --repo GoGrabSpace/editor | grep -E "IOS_|ANDROID_|APPSTORE_|GOOGLE_PLAY"
# Should show 12 secrets (APPLE_TEAM_ID is shared)

Phase E: First Test Build Verification

E1. Local iOS Simulator Test

cd /Users/fguijarro/developer/repos-gspace/gspace1
yarn nx build app-gograb-ai --configuration=production
cd apps/vitto-mobile
npx cap sync
npx cap run ios

Verify:

E2. Local Android Emulator Test

npx cap run android

Verify:

E3. Auth Flow E2E Test

  1. Launch app on simulator → should show /welcome
  2. Click "Sign in with GoGrab"
  3. System browser opens ai.gograb.space/auth/desktop
  4. Log in with test account
  5. Browser redirects to vitto://auth?token=...&user=...
  6. App receives deep link → stores token → reloads
  7. Dashboard loads with authenticated user

Note: Deep link testing on iOS Simulator requires manually opening the URL:

xcrun simctl openurl booted "vitto://auth?token=TEST_TOKEN&user=TEST_USER_B64"

E4. CI Pipeline Dry Run

Once all 13 secrets are set:

# Create a release candidate tag to test the pipeline:
git tag vitto-mobile-v0.1.0-rc.1
git push origin vitto-mobile-v0.1.0-rc.1

Monitor: GitHub Actions > Release Vitto Mobile

Verify:


Phase F: App Store Submission

F1. iOS — Submit for Review

  1. App Store Connect > My Apps > Vitto
  2. Under the version (e.g., 1.0):
    • Add screenshots (from Phase B4)
    • Fill promotional text: "AI assistant powered by GoGrab Space"
    • Fill description (2-3 paragraphs about Vitto's capabilities)
    • Add keywords: AI, assistant, productivity, automation, chat
    • Support URL: https://gograb.space/support
    • Marketing URL: https://gograb.space
  3. Under "Build": Select the TestFlight build uploaded by CI
  4. Under "App Review Information": Add demo credentials
  5. Click "Submit for Review"

Expected timeline: 1-5 business days for first submission. Subsequent updates are usually faster (24-48h).

F2. Android — Promote to Production

  1. Google Play Console > Vitto - AI Assistant
  2. Complete the store listing:
    • Short description (80 chars): "AI assistant for GoGrab Space"
    • Full description: Same as iOS
    • Screenshots (phone required, tablet optional)
    • Feature graphic: 1024 x 500 px
    • App icon: 512 x 512 px
  3. Complete the content rating questionnaire (IARC)
  4. Set up pricing: Free
  5. Complete the Data Safety section (similar to iOS privacy disclosure)
  6. Internal testing > Promote to Production (or Open testing first)

Expected timeline: Usually 1-3 days for first review.


Troubleshooting

Problem Solution
xcodebuild fails with "No provisioning profile" Ensure profile is installed in ~/Library/MobileDevice/Provisioning Profiles/ and bundle ID matches exactly
TestFlight upload fails with "Invalid API key" Verify APPSTORE_API_KEY_ID matches the key, and the .p8 is base64-encoded (not double-encoded)
gradlew bundleRelease signing error Verify keystore path, password, alias, and key password all match
fastlane supply returns 403 Service account needs "Release to production" permission in Play Console
"App not found" on first fastlane supply run You must upload the first AAB manually via Play Console (step C4)
Build number already used (TestFlight) CI uses github.run_number which always increments. If testing locally, use a higher build number
iOS app rejected for "Login required" Provide demo account credentials in App Review Information

Key Files Reference

File Purpose
apps/vitto-mobile/capacitor.config.ts Capacitor config (appId, webDir, plugins)
apps/vitto-mobile/ios/App/App/Info.plist iOS URL scheme (vitto://) registration
apps/vitto-mobile/android/app/src/main/AndroidManifest.xml Android deep link intent filter
apps/vitto-mobile/android/app/build.gradle Android version info
apps/gograb-ai/src/app/pages/desktop-welcome/desktop-welcome.component.ts Auth flow (Tauri + Capacitor)
apps/gograb-ai/src/app/core/services/capacitor-bridge.service.ts Capacitor native bridge
.github/workflows/release-vitto-mobile.yml CI/CD pipeline
tools/scripts/release/release-vitto-mobile.js Release script
deployment/docs/VITTO-MOBILE-SIGNING-SETUP.md Signing guide
deployment/docs/VITTO-MOBILE-RELEASE.md Release workflow

Handoff Acceptance Criteria

This handoff is complete when: