Everything you need to set up before going to production.
Use this as a checklist. You can also ask Claude to help you with each step:
"Help me complete step 2.1 - create a GCP project"
Install these on your machine:
| Tool | Install Command | Verify |
|---|---|---|
| Go 1.24+ | brew install go |
go version |
| Node.js | brew install node |
node --version |
| gcloud CLI | Install Guide | gcloud version |
| Pulumi | brew install pulumi |
pulumi version |
| Firebase CLI | npm install -g firebase-tools |
firebase --version |
| XcodeGen | brew install xcodegen |
xcodegen --version |
| Claude Code | npm install -g @anthropic-ai/claude-code |
claude --version |
For iOS development:
- Xcode 15+ (from App Store)
- Apple Developer account (for device testing)
For Android development:
- Android Studio
- Android SDK (installed via Android Studio)
You need at least one project. Recommended: separate dev and prod.
# Development project
gcloud projects create YOUR-APP-dev --name="Your App Dev"
# Production project (optional but recommended)
gcloud projects create YOUR-APP-prod --name="Your App Prod"Record these:
- Dev Project ID:
_______________ - Prod Project ID:
_______________
Go to GCP Console → Billing → Link a billing account.
- Billing enabled on dev project
- Billing enabled on prod project
The setup script does this, but you can do it manually:
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com \
firestore.googleapis.com \
secretmanager.googleapis.com \
firebase.googleapis.com \
--project=YOUR-PROJECT-ID- APIs enabled on dev project
- APIs enabled on prod project
# Login to gcloud
gcloud auth login
# Set application default credentials
gcloud auth application-default login
# Set default project
gcloud config set project YOUR-PROJECT-ID- gcloud authenticated
- Application default credentials set
- Go to Firebase Console
- Click "Add project"
- Select your existing GCP project
- Follow the wizard
- Firebase project created (dev)
- Firebase project created (prod)
- Firebase Console → Build → Firestore Database
- Click "Create database"
- Choose "Start in production mode"
- Select region:
us-central1(recommended)
- Firestore enabled (dev)
- Firestore enabled (prod)
- Firebase Console → Build → Authentication
- Click "Get started"
- Enable providers:
- Email/Password
- Apple (for iOS)
For iOS:
- Firebase Console → Project Settings → Your apps → iOS
- Register your iOS app (bundle ID:
com.yourcompany.yourapp) - Download
GoogleService-Info.plist - Place in
mobile/ios/App/
- GoogleService-Info.plist downloaded
For Android:
- Firebase Console → Project Settings → Your apps → Android
- Register your Android app (package:
com.yourcompany.yourapp) - Download
google-services.json - Place in
mobile/android/app/
- google-services.json downloaded
cd infrastructure/pulumi
pulumi login --local # Or use Pulumi Cloud- Pulumi logged in
# Development stack
pulumi config set gcp:project YOUR-DEV-PROJECT-ID --stack dev
pulumi config set gcp:region us-central1 --stack dev
# Production stack
pulumi config set gcp:project YOUR-PROD-PROJECT-ID --stack prod
pulumi config set gcp:region us-central1 --stack prod- Dev stack configured
- Prod stack configured
# Deploy dev first
make deploy-dev
# Once verified, deploy prod
make deploy-prod- Dev infrastructure deployed
- Prod infrastructure deployed
Record outputs:
- Dev Cloud Run URL:
_______________ - Prod Cloud Run URL:
_______________
- Create new repo
- Make it public or private
- Don't initialize with README (you have one)
- GitHub repo created
- Repo URL:
_______________
Go to: Repository → Settings → Secrets and variables → Actions
| Secret Name | Value | Where to Get It |
|---|---|---|
GCP_PROJECT_ID |
Your GCP project ID | GCP Console |
WIF_PROVIDER |
Workload Identity provider | See 5.3 |
WIF_SERVICE_ACCOUNT |
Service account email | See 5.3 |
-
GCP_PROJECT_IDsecret added -
WIF_PROVIDERsecret added -
WIF_SERVICE_ACCOUNTsecret added
This allows GitHub Actions to deploy without service account keys.
PROJECT_ID=YOUR-PROJECT-ID
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
# Create service account
gcloud iam service-accounts create github-actions \
--display-name="GitHub Actions" \
--project=$PROJECT_ID
# Grant permissions
SA_EMAIL="github-actions@${PROJECT_ID}.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/run.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/artifactregistry.writer"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/iam.serviceAccountUser"
# Create workload identity pool
gcloud iam workload-identity-pools create "github" \
--location="global" \
--display-name="GitHub Actions Pool" \
--project=$PROJECT_ID
# Create provider
gcloud iam workload-identity-pools providers create-oidc "github" \
--location="global" \
--workload-identity-pool="github" \
--display-name="GitHub" \
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
--issuer-uri="https://token.actions.githubusercontent.com" \
--project=$PROJECT_ID
# Allow GitHub to impersonate service account
REPO="YOUR-GITHUB-USERNAME/YOUR-REPO-NAME"
gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/github/attribute.repository/${REPO}" \
--project=$PROJECT_IDRecord these for GitHub secrets:
-
WIF_PROVIDER:projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github/providers/github -
WIF_SERVICE_ACCOUNT:github-actions@PROJECT_ID.iam.gserviceaccount.com -
Workload Identity Federation configured
-
GitHub secrets updated
- Apple Developer Program membership ($99/year)
- App ID created in Apple Developer Portal
- Provisioning profiles created
- Certificates exported
- Google Play Developer account ($25 one-time)
- App created in Play Console
- Signing key generated
- Upload key configured
Run through this to verify everything works:
# Backend runs locally
cd backend && make run
# Visit http://localhost:8080/health
# iOS builds
cd mobile/ios && xcodegen generate && open App.xcodeproj
# Build in Xcode
# Android builds
cd mobile/android && ./gradlew assembleDebug
# Or open in Android Studio
# Infrastructure deploys
cd infrastructure/pulumi && make preview-dev
# CI runs (push a commit)
git push origin main
# Check GitHub Actions- Backend runs locally
- iOS builds successfully
- Android builds successfully
- Pulumi preview works
- GitHub Actions run successfully
| What | Where to Find It |
|---|---|
| GCP Project ID | GCP Console → Project selector |
| GCP Project Number | GCP Console → Project settings |
| Firebase Project ID | Firebase Console → Project settings |
| Service Account Email | GCP Console → IAM → Service accounts |
| WIF Provider | Format: projects/NUMBER/locations/global/workloadIdentityPools/github/providers/github |
| Cloud Run URL | Pulumi outputs or GCP Console → Cloud Run |
Ask Claude:
"I'm stuck on step 5.3 - help me set up Workload Identity Federation for my GitHub repo"
Claude can run the commands for you if you have the right permissions.
Production is a series of checkboxes. Check them all.