Local Development
Prerequisites
- Docker (for Spanner/Firebase emulators and service containers)
- Bazel (builds all services)
- pnpm (for frontend websites)
- Python 3 (for dev scripts)
Quick Start
# Start all backend services (Spanner emulator + Firebase emulator + 6 services)
./scripts/dev.sh services
# Start everything including admin portal frontend
./scripts/dev.sh all
# Stop all services
./scripts/dev.sh stop
What dev.sh services Does
- Starts Spanner emulator: gRPC on host port 9110, REST on host port 9120
- Starts Firebase Auth emulator: port 9199, UI at port 4100
- Builds OCI images:
bazel buildfor all 6 services - Loads images into Docker: incremental (skips unchanged images)
- Starts docker-compose: all 6 services with host networking
- Health polls: waits up to 60s for all services to report healthy
Service Ports
| Service | HTTP | PGAdapter | Docker Container |
|---|---|---|---|
| auth | 8081 | 9432 | dev-gateway-auth |
| processing | 8082 | 9433 | dev-gateway-processing |
| management | 8083 | 9434 | dev-gateway-management |
| online-txn | 8084 | 9435 | dev-gateway-online-txn |
| merchant-onboarding | 8085 | 9436 | dev-gateway-merchant-onboarding |
| status | 8086 | - | dev-gateway-status |
Emulators
| Service | Port | Notes |
|---|---|---|
| Spanner (gRPC) | 9110 | SPANNER_EMULATOR_HOST=localhost:9110 |
| Spanner (REST) | 9120 | |
| Firebase Auth | 9199 | FIREBASE_AUTH_EMULATOR_HOST=localhost:9199 |
| Firebase UI | 4100 | Browser-accessible at http://localhost:4100 |
Dev Commands
./scripts/dev.sh all # Everything
./scripts/dev.sh services # Backend services only
./scripts/dev.sh portal # Admin Portal frontend (Vite HMR on :5173)
./scripts/dev.sh infra # Emulators only
./scripts/dev.sh stop # Stop everything
./scripts/dev.sh status # Show what's running
./scripts/dev.sh logs auth # Tail specific service logs
Running Individual Services
# Build and run a single service directly (needs emulators running)
./scripts/dev.sh infra
source scripts/dev.env
bazel run //services/processing:core
Running Tests
# All tests
bazel test //...
# Single test
bazel test //services/processing:subscription_service_test
# Test with output
bazel test //services/processing:subscription_service_test --test_output=all
Frontend Development
# Admin Portal dev server (hot reload)
bazel run //websites/admin-portal:start
# Or directly with pnpm (from websites/admin-portal/)
pnpm dev
When you use the shared local stack from ./scripts/dev.sh, frontend apps talk to the backend services on the docker-mapped host ports (8181-8186). Host-run services should source scripts/dev.env so internal proxy calls use those same mapped ports.
Frontend apps connect to the Firebase Auth emulator in local dev when VITE_FIREBASE_AUTH_EMULATOR_HOST=localhost:9199 is present in the app env file.
Common Issues
| Issue | Fix |
|---|---|
| Docker not running | Start Docker Desktop or systemctl start docker |
| Port already in use | ./scripts/dev.sh stop then retry, or lsof -i :PORT to find process |
| Stale image | ./scripts/dev.sh stop && ./scripts/dev.sh services forces rebuild |
| Spanner emulator won't start | Check Docker is running and port 9110 is free |
| Firebase emulator port conflict | Check port 9199 is free (lsof -i :9199) |