Staging Environment Setup¶
Master Schedule uses two completely separate Firebase projects — one for production and one for staging — so that test data never touches real school data. Each project has its own Firestore database, Authentication user pool, and four Hosting sites.
| Production | Staging | |
|---|---|---|
| Firebase project | masterschedule-prod |
masterschedule-staging |
| Public site | masterschedule.app |
masterschedule-public-staging.web.app |
| App URL | app.masterschedule.app |
masterschedule-app-staging.web.app |
| Help URL | help.masterschedule.app |
masterschedule-help-staging.web.app |
| Admin URL | admin.masterschedule.app |
masterschedule-admin-staging.web.app |
Project structure¶
masterschedule-prod (Firebase project)
├── masterschedule-public Public marketing site
├── masterschedule-app Main scheduling app
├── masterschedule-help Help documentation
└── masterschedule-admin Admin console
masterschedule-staging (Firebase project)
├── masterschedule-public-staging
├── masterschedule-app-staging
├── masterschedule-help-staging
└── masterschedule-admin-staging
One-time setup¶
1. Enable Firestore and Authentication in each project¶
In both masterschedule-prod and masterschedule-staging:
- Go to Build → Firestore Database → Create database (production mode).
- Go to Authentication → Sign-in method and enable the Google provider.
2. Deploy security rules¶
./deploy.sh --rules-staging
./deploy.sh --rules-prod # prompts for confirmation
3. Set up the Firestore TTL policy¶
Follow the same steps in each project — see Audit Log TTL Policy Setup.
4. Add yourself as superadmin¶
In each project's Firestore, create a document at superadmins/{your-uid}:
email: "your@email.com"
grantedAt: <current timestamp>
Find your UID in Authentication → Users for each project.
Deploying to staging¶
# App + admin + public site
./deploy.sh --staging
# Help docs only
./deploy.sh --help-staging
# Rules only
./deploy.sh --rules-staging
# Everything at once
./deploy.sh --all
The deploy script automatically injects the correct Firebase config (including the per-site appId) before uploading, then restores the production config when finished so local development is unaffected.
Deploying to production¶
# App + admin + public site (prompts for confirmation)
./deploy.sh --production
# Help docs (prompts for confirmation)
./deploy.sh --help-prod
# Rules (prompts for confirmation)
./deploy.sh --rules-prod
Firebase config management¶
Each site has its own Firebase web app registration and appId. All shared credentials (API key, project ID, etc.) are stored in env/firebase.prod.json and env/firebase.staging.json. The deploy script picks the correct appId per site automatically.
To write config files manually without deploying:
./deploy.sh --write-config staging
./deploy.sh --write-config prod
Loading test data¶
Production data must never be copied directly to staging. Use one of:
- Manually created test data — create schools, teachers, and courses by hand in the staging app. This is the required approach until the data sanitizer is built.
- Data sanitizer (pending) — a script that anonymizes a production Firestore export and imports it into staging. See Data Architecture.
Security rules¶
Both projects run the same firestore.rules and storage.rules files. When you change rules, deploy to both:
./deploy.sh --rules
This deploys to staging first, then prompts before deploying to production.