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:
- Go to Certificates, Identifiers & Profiles > Certificates
- Click (+) > Select Apple Distribution
- Create a Certificate Signing Request (CSR):
- Open Keychain Access > Certificate Assistant > Request a Certificate from a CA
- Enter your email, select "Saved to disk"
- Upload the CSR, download the
.cerfile - Double-click the
.certo install it in Keychain - In Keychain Access, find the certificate under "My Certificates"
- 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 -ithen pipe into anotherbase64 -i. That double-encodes. Same lesson learned from Session 141.7 with Tauri signing key.
A2. Register App ID
- Go to Identifiers > (+)
- Select App IDs > Continue
- Platform: iOS
- Description:
Vitto Mobile - Bundle ID: Explicit >
space.gograb.vitto.mobile - Capabilities: Check Push Notifications
- Optionally check Associated Domains (for future Universal Links)
- Click Continue > Register
Verification: The App ID space.gograb.vitto.mobile appears in the Identifiers list.
A3. Create App Store Provisioning Profile
- Go to Profiles > (+)
- Select App Store Connect under Distribution
- Select App ID:
space.gograb.vitto.mobile - Select Certificate: the Apple Distribution certificate from step A1
- Name it:
Vitto Mobile App Store - Download the
.mobileprovisionfile
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
- Go to Users and Access > Integrations > App Store Connect API
- Click (+) to generate a new API key
- Name:
Vitto GitHub Actions - Access: App Manager (minimum role for TestFlight upload)
- IMMEDIATELY download the .p8 file — this is a one-time download, Apple will not let you download it again
- Note the Key ID (shown on the page, e.g.,
XXXXXXXXXX) - 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:
APPSTORE_API_KEY_ID= the Key IDAPPSTORE_API_ISSUER_ID= the Issuer IDAPPSTORE_API_KEY_BASE64= the base64-encoded .p8
B2. Create the App in App Store Connect
- Go to My Apps > (+) > New App
- Platform: iOS
- Name:
Vitto - Primary Language: English (U.S.)
- Bundle ID: select
space.gograb.vitto.mobile(registered in step A2) - SKU:
vitto-mobile - User Access: Full Access
B3. Fill Required App Information
Under App Information:
- Category: Productivity
- Content Rights: Does not contain third-party content
- Age Rating: Complete the questionnaire (no objectionable content)
Under App Privacy:
- Privacy Policy URL:
https://gograb.space/privacy - Data collection disclosure: the app collects:
- Email address (for authentication)
- User ID (for account management)
- Usage data (chat messages sent to AI)
- None of this data is sold
Under Pricing and Availability:
- Price: Free
- Availability: All territories (or select specific ones)
B4. Prepare Screenshots
Required minimum sizes:
- 6.7-inch (iPhone 15 Pro Max): 1290 x 2796 px
- 6.5-inch (iPhone 11 Pro Max): 1242 x 2688 px
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):
- Welcome/Sign-in screen
- Main dashboard after login
- AI chat conversation
- Settings or profile view
B5. App Review Information
- Contact: Your name, email, phone
- Demo Account: Provide test credentials (username + password) for the App Store review team
- Notes: "Vitto is an AI assistant integrated with the GoGrab Space platform. The app requires authentication via the GoGrab account system. Use the provided test credentials to access the full functionality."
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:
ANDROID_KEYSTORE_BASE64= the base64-encoded .jksANDROID_KEYSTORE_PASSWORD= the storepass you choseANDROID_KEY_ALIAS=vitto-uploadANDROID_KEY_PASSWORD= the keypass you chose
IMPORTANT: Back up
~/.android/vitto-upload.jkssecurely. 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:
- Go to https://play.google.com/console/signup
- Pay $25 one-time registration fee
- 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
- Go to All apps > Create app
- App name:
Vitto - AI Assistant - Default language: English (United States)
- App or game: App
- Free or paid: Free
- 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:
- Google Play Console > your app > Testing > Internal testing
- Create new release
- Upload
app-release.aab - Add release notes: "Initial internal test build"
- Review and start rollout
Verification: The Internal testing track shows "Available to internal testers".
C5. Create Google Play Service Account
- Go to Google Cloud Console (https://console.cloud.google.com)
- Select/create a project for GoGrab
- IAM & Admin > Service Accounts > Create Service Account
- Name:
vitto-github-deploy - Role: Service Account User
- Click Create and Continue
- Under the new service account: Keys > Add Key > Create New Key > JSON
- Download the JSON key file
Link to Play Console:
- Google Play Console > Settings > API access
- Link the Google Cloud project
- Find
vitto-github-deployin the service accounts list - 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:
- App launches with cosmic orbital loader
- Welcome screen shows with "v0.1.0 - Mobile" badge
- "Sign in with GoGrab" button opens system browser
- Status bar is dark with correct background (#0f172a)
- No black bars around content (safe-area working)
- Splash screen shows for ~2s before app loads
E2. Local Android Emulator Test
npx cap run android
Verify:
- App launches on Android emulator
- Same checks as iOS above
- Deep link intent filter registered (check via
adb shell dumpsys package space.gograb.vitto.mobile | grep vitto)
E3. Auth Flow E2E Test
- Launch app on simulator → should show
/welcome - Click "Sign in with GoGrab"
- System browser opens
ai.gograb.space/auth/desktop - Log in with test account
- Browser redirects to
vitto://auth?token=...&user=... - App receives deep link → stores token → reloads
- 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:
-
build-webjob succeeds (Angular build) -
build-iosjob succeeds (xcodebuild + TestFlight upload) -
build-androidjob succeeds (Gradle + Play Store upload) -
create-releasejob creates a draft GitHub Release - TestFlight shows the new build (check on a real device with TestFlight installed)
- Google Play Console > Internal testing shows the new build
Phase F: App Store Submission
F1. iOS — Submit for Review
- App Store Connect > My Apps > Vitto
- 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
- Under "Build": Select the TestFlight build uploaded by CI
- Under "App Review Information": Add demo credentials
- 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
- Google Play Console > Vitto - AI Assistant
- 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
- Complete the content rating questionnaire (IARC)
- Set up pricing: Free
- Complete the Data Safety section (similar to iOS privacy disclosure)
- 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:
- App is running on iOS Simulator and Android Emulator
- Auth flow works end-to-end (sign in via browser → deep link → dashboard)
- All 13 GitHub secrets are configured
- CI pipeline produces .ipa and .aab on tag push
- TestFlight has at least one build available
- Google Play internal testing has at least one build available
- App Store submission is "In Review" or "Ready for Sale"
- Google Play submission is "In Review" or "Published"