@terreno/mcp 56.0.0-beta.0 → 57.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bootstrap.d.ts.map +1 -1
  3. package/dist/bootstrap.js +10 -11
  4. package/dist/bootstrap.js.map +1 -1
  5. package/dist/docs/templates/bootstrap/backend/types/models/userTypes.template.md +5 -4
  6. package/dist/docs/templates/tools/model.template.md +4 -2
  7. package/dist/docs/upgrades/0.31.0.md +60 -0
  8. package/dist/docs/upgrades/56.0.0-beta.2.md +59 -0
  9. package/dist/docs/upgrades/57.0.0-beta.1.md +41 -0
  10. package/dist/docs/versioned/next/README.md +1 -0
  11. package/dist/docs/versioned/next/explanation/README.md +7 -1
  12. package/dist/docs/versioned/next/explanation/deployment-architecture-gcp.md +65 -0
  13. package/dist/docs/versioned/next/explanation/deployment-baseline.md +78 -0
  14. package/dist/docs/versioned/next/explanation/positioning.md +164 -0
  15. package/dist/docs/versioned/next/explanation/repository-settings.md +44 -0
  16. package/dist/docs/versioned/next/explanation/roadmap-process.md +330 -0
  17. package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +887 -0
  18. package/dist/docs/versioned/next/how-to/README.md +8 -0
  19. package/dist/docs/versioned/next/how-to/build-for-web.md +69 -0
  20. package/dist/docs/versioned/next/how-to/deploy-backend-to-cloud-run.md +115 -0
  21. package/dist/docs/versioned/next/how-to/deploy-to-gcp.md +20 -228
  22. package/dist/docs/versioned/next/how-to/deploy-web-to-gcs-cdn.md +183 -0
  23. package/dist/docs/versioned/next/implementationPlans/PLAN_INDEX.md +31 -0
  24. package/dist/docs/versioned/next/implementationPlans/README.md +56 -30
  25. package/dist/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +2 -1
  26. package/dist/docs/versioned/next/implementationPlans/ai-dev-loop-boost.md +1 -0
  27. package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +115 -0
  28. package/dist/docs/versioned/next/implementationPlans/billing-stripe.md +158 -0
  29. package/dist/docs/versioned/next/implementationPlans/build-terreno-app-validation.md +1 -0
  30. package/dist/docs/versioned/next/implementationPlans/comms-abstraction.md +323 -0
  31. package/dist/docs/versioned/next/implementationPlans/comms-adapter-expo-push.md +107 -0
  32. package/dist/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +157 -0
  33. package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +155 -0
  34. package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +99 -0
  35. package/dist/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +180 -0
  36. package/dist/docs/versioned/next/implementationPlans/deploy-to-gcp.md +1 -0
  37. package/dist/docs/versioned/next/implementationPlans/deploy-to-vercel.md +1 -0
  38. package/dist/docs/versioned/next/implementationPlans/deployment-foundation.md +1 -0
  39. package/dist/docs/versioned/next/implementationPlans/docs-reference-coverage.md +1 -0
  40. package/dist/docs/versioned/next/implementationPlans/docs-tutorials-ai-first.md +1 -0
  41. package/dist/docs/versioned/next/implementationPlans/examples-demo-coverage.md +1 -0
  42. package/dist/docs/versioned/next/implementationPlans/infra-mcp-research.md +188 -0
  43. package/dist/docs/versioned/next/implementationPlans/infra-mcp.md +269 -0
  44. package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +126 -0
  45. package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +269 -0
  46. package/dist/docs/versioned/next/implementationPlans/native-module-baseline.md +105 -0
  47. package/dist/docs/versioned/next/implementationPlans/orgs-and-teams.md +158 -0
  48. package/dist/docs/versioned/next/implementationPlans/oss-governance-baseline.md +1 -0
  49. package/dist/docs/versioned/next/implementationPlans/password-reset-and-email-verification.md +147 -0
  50. package/dist/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -0
  51. package/dist/docs/versioned/next/implementationPlans/public-roadmap-github.md +1 -0
  52. package/dist/docs/versioned/next/implementationPlans/upgrade-guides-and-skill.md +1 -0
  53. package/dist/docs/versioned/next/implementationPlans/web-ssr-and-admin-spa.md +1 -0
  54. package/dist/docs/versioned/next/reference/README.md +5 -0
  55. package/dist/docs/versioned/next/reference/admin-spa.md +130 -0
  56. package/dist/docs/versioned/next/reference/ai.md +519 -0
  57. package/dist/docs/versioned/next/reference/comms.md +132 -0
  58. package/dist/docs/versioned/next/reference/environment-variables.md +229 -382
  59. package/dist/docs/versioned/next/reference/test.md +108 -0
  60. package/dist/docs/versioned/next/roadmap.md +9 -0
  61. package/dist/docs/versioned/next/tasks/README.md +42 -0
  62. package/dist/docs/versioned/next/tasks/agentic-sdlc-plugin.md +5 -5
  63. package/dist/docs/versioned/next/tasks/billing-stripe.md +75 -0
  64. package/dist/docs/versioned/next/tasks/comms-abstraction.md +90 -0
  65. package/dist/docs/versioned/next/tasks/comms-adapter-expo-push.md +29 -0
  66. package/dist/docs/versioned/next/tasks/comms-adapter-sendgrid.md +39 -0
  67. package/dist/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +39 -0
  68. package/dist/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +19 -0
  69. package/dist/docs/versioned/next/tasks/comms-admin-dashboard.md +52 -0
  70. package/dist/docs/versioned/next/tasks/deploy-to-gcp.md +11 -11
  71. package/dist/docs/versioned/next/tasks/deployment-foundation.md +12 -12
  72. package/dist/docs/versioned/next/tasks/docs-reference-coverage.md +4 -4
  73. package/dist/docs/versioned/next/tasks/infra-mcp.md +43 -0
  74. package/dist/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +215 -0
  75. package/dist/docs/versioned/next/tasks/native-module-baseline.md +42 -0
  76. package/dist/docs/versioned/next/tasks/orgs-and-teams.md +70 -0
  77. package/dist/docs/versioned/next/tasks/oss-governance-baseline.md +18 -18
  78. package/dist/docs/versioned/next/tasks/password-reset-and-email-verification.md +60 -0
  79. package/dist/docs/versioned/next/tasks/positioning-django-rails-universal.md +4 -4
  80. package/dist/docs/versioned/next/tasks/public-roadmap-github.md +15 -15
  81. package/package.json +4 -3
  82. package/src/docs/templates/bootstrap/backend/types/models/userTypes.template.md +5 -4
  83. package/src/docs/templates/tools/model.template.md +4 -2
  84. package/src/docs/upgrades/0.31.0.md +60 -0
  85. package/src/docs/upgrades/56.0.0-beta.2.md +59 -0
  86. package/src/docs/upgrades/57.0.0-beta.1.md +41 -0
  87. package/src/docs/versioned/next/README.md +1 -0
  88. package/src/docs/versioned/next/explanation/README.md +7 -1
  89. package/src/docs/versioned/next/explanation/deployment-architecture-gcp.md +65 -0
  90. package/src/docs/versioned/next/explanation/deployment-baseline.md +78 -0
  91. package/src/docs/versioned/next/explanation/positioning.md +164 -0
  92. package/src/docs/versioned/next/explanation/repository-settings.md +44 -0
  93. package/src/docs/versioned/next/explanation/roadmap-process.md +330 -0
  94. package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +887 -0
  95. package/src/docs/versioned/next/how-to/README.md +8 -0
  96. package/src/docs/versioned/next/how-to/build-for-web.md +69 -0
  97. package/src/docs/versioned/next/how-to/deploy-backend-to-cloud-run.md +115 -0
  98. package/src/docs/versioned/next/how-to/deploy-to-gcp.md +20 -228
  99. package/src/docs/versioned/next/how-to/deploy-web-to-gcs-cdn.md +183 -0
  100. package/src/docs/versioned/next/implementationPlans/PLAN_INDEX.md +31 -0
  101. package/src/docs/versioned/next/implementationPlans/README.md +56 -30
  102. package/src/docs/versioned/next/implementationPlans/agentic-sdlc-plugin.md +2 -1
  103. package/src/docs/versioned/next/implementationPlans/ai-dev-loop-boost.md +1 -0
  104. package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +115 -0
  105. package/src/docs/versioned/next/implementationPlans/billing-stripe.md +158 -0
  106. package/src/docs/versioned/next/implementationPlans/build-terreno-app-validation.md +1 -0
  107. package/src/docs/versioned/next/implementationPlans/comms-abstraction.md +323 -0
  108. package/src/docs/versioned/next/implementationPlans/comms-adapter-expo-push.md +107 -0
  109. package/src/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +157 -0
  110. package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +155 -0
  111. package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +99 -0
  112. package/src/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +180 -0
  113. package/src/docs/versioned/next/implementationPlans/deploy-to-gcp.md +1 -0
  114. package/src/docs/versioned/next/implementationPlans/deploy-to-vercel.md +1 -0
  115. package/src/docs/versioned/next/implementationPlans/deployment-foundation.md +1 -0
  116. package/src/docs/versioned/next/implementationPlans/docs-reference-coverage.md +1 -0
  117. package/src/docs/versioned/next/implementationPlans/docs-tutorials-ai-first.md +1 -0
  118. package/src/docs/versioned/next/implementationPlans/examples-demo-coverage.md +1 -0
  119. package/src/docs/versioned/next/implementationPlans/infra-mcp-research.md +188 -0
  120. package/src/docs/versioned/next/implementationPlans/infra-mcp.md +269 -0
  121. package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +126 -0
  122. package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +269 -0
  123. package/src/docs/versioned/next/implementationPlans/native-module-baseline.md +105 -0
  124. package/src/docs/versioned/next/implementationPlans/orgs-and-teams.md +158 -0
  125. package/src/docs/versioned/next/implementationPlans/oss-governance-baseline.md +1 -0
  126. package/src/docs/versioned/next/implementationPlans/password-reset-and-email-verification.md +147 -0
  127. package/src/docs/versioned/next/implementationPlans/positioning-django-rails-universal.md +1 -0
  128. package/src/docs/versioned/next/implementationPlans/public-roadmap-github.md +1 -0
  129. package/src/docs/versioned/next/implementationPlans/upgrade-guides-and-skill.md +1 -0
  130. package/src/docs/versioned/next/implementationPlans/web-ssr-and-admin-spa.md +1 -0
  131. package/src/docs/versioned/next/reference/README.md +5 -0
  132. package/src/docs/versioned/next/reference/admin-spa.md +130 -0
  133. package/src/docs/versioned/next/reference/ai.md +519 -0
  134. package/src/docs/versioned/next/reference/comms.md +132 -0
  135. package/src/docs/versioned/next/reference/environment-variables.md +229 -382
  136. package/src/docs/versioned/next/reference/test.md +108 -0
  137. package/src/docs/versioned/next/roadmap.md +9 -0
  138. package/src/docs/versioned/next/tasks/README.md +42 -0
  139. package/src/docs/versioned/next/tasks/agentic-sdlc-plugin.md +5 -5
  140. package/src/docs/versioned/next/tasks/billing-stripe.md +75 -0
  141. package/src/docs/versioned/next/tasks/comms-abstraction.md +90 -0
  142. package/src/docs/versioned/next/tasks/comms-adapter-expo-push.md +29 -0
  143. package/src/docs/versioned/next/tasks/comms-adapter-sendgrid.md +39 -0
  144. package/src/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +39 -0
  145. package/src/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +19 -0
  146. package/src/docs/versioned/next/tasks/comms-admin-dashboard.md +52 -0
  147. package/src/docs/versioned/next/tasks/deploy-to-gcp.md +11 -11
  148. package/src/docs/versioned/next/tasks/deployment-foundation.md +12 -12
  149. package/src/docs/versioned/next/tasks/docs-reference-coverage.md +4 -4
  150. package/src/docs/versioned/next/tasks/infra-mcp.md +43 -0
  151. package/src/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +215 -0
  152. package/src/docs/versioned/next/tasks/native-module-baseline.md +42 -0
  153. package/src/docs/versioned/next/tasks/orgs-and-teams.md +70 -0
  154. package/src/docs/versioned/next/tasks/oss-governance-baseline.md +18 -18
  155. package/src/docs/versioned/next/tasks/password-reset-and-email-verification.md +60 -0
  156. package/src/docs/versioned/next/tasks/positioning-django-rails-universal.md +4 -4
  157. package/src/docs/versioned/next/tasks/public-roadmap-github.md +15 -15
@@ -2,6 +2,14 @@
2
2
 
3
3
  Problem-oriented, practical steps. Use these when you know what you want to do.
4
4
 
5
+ ## Deployment
6
+
7
+ - [Deployment baseline](../explanation/deployment-baseline.md) — seven requirements every host must satisfy
8
+ - [Build for web](build-for-web.md) — export static web bundle with correct API URL
9
+ - [Deploy to Google Cloud Platform](deploy-to-gcp.md) — index for GCP guides
10
+ - [Deploy backend to Cloud Run](deploy-backend-to-cloud-run.md) — container + Secret Manager + Cloud Run
11
+ - [Deploy web to GCS + CDN](deploy-web-to-gcs-cdn.md) — static hosting with SPA routing
12
+
5
13
  ## Contents
6
14
 
7
15
  - [Create a Mongoose model](create-a-model.md) — Define models with proper conventions
@@ -0,0 +1,69 @@
1
+ # Build for web
2
+
3
+ Export your Terreno Expo app as static files for hosting on GCS, Netlify, or any CDN.
4
+
5
+ See the [deployment baseline](../explanation/deployment-baseline.md) for requirements that apply to every host.
6
+
7
+ ## Prerequisites
8
+
9
+ - Backend running and reachable from browsers (CORS configured).
10
+ - MongoDB replica set for realtime features (see baseline).
11
+
12
+ ## 1. Set the API URL at build time
13
+
14
+ `EXPO_PUBLIC_API_URL` is **inlined into the JavaScript bundle** during export. Setting it on the hosting platform after deploy does nothing.
15
+
16
+ ```bash
17
+ cd example-frontend
18
+ EXPO_PUBLIC_API_URL=https://api.example.com bun run export
19
+ ```
20
+
21
+ The export script in `example-frontend/package.json` is:
22
+
23
+ ```bash
24
+ bun expo export --platform web
25
+ ```
26
+
27
+ ### Alternative: `app.json` `extra.BASE_URL`
28
+
29
+ `@terreno/rtk` resolves the API base from `expo-constants` `extra.BASE_URL` and `EXPO_PUBLIC_API_URL` (see `rtk/src/constants.ts` `resolveBaseUrls`). Priority in **production** builds:
30
+
31
+ 1. `EXPO_PUBLIC_API_URL` environment variable (set before export)
32
+ 2. `extra.BASE_URL` in app config (when env var is unset)
33
+ 3. Development fallbacks (hostUri, experience URL, localhost) — only in `__DEV__`
34
+
35
+ For production, prefer `EXPO_PUBLIC_API_URL` so CI and local builds behave the same.
36
+
37
+ ## 2. Run the export
38
+
39
+ ```bash
40
+ EXPO_PUBLIC_API_URL=https://api.example.com bun run export
41
+ ```
42
+
43
+ Output lands in `dist/` (Expo default for web export). Contents depend on the configured web `output` mode — today Terreno apps use the `single` SPA mode (one `index.html`).
44
+
45
+ ## 3. Verify locally before uploading
46
+
47
+ Serve the `dist/` folder with any static server and confirm API calls hit your backend:
48
+
49
+ ```bash
50
+ npx serve dist -p 4173
51
+ ```
52
+
53
+ Open `http://localhost:4173`, log in, and check the network tab — requests must go to your `EXPO_PUBLIC_API_URL`, not `localhost`.
54
+
55
+ ## 4. Deploy the static files
56
+
57
+ Upload `dist/` to your host. **Client-side routing** requires the host to serve `index.html` for unknown paths (SPA fallback):
58
+
59
+ | Host | Configuration |
60
+ |------|---------------|
61
+ | GCS + CDN | `notFoundPage=index.html` on the bucket — see [Deploy web to GCS + CDN](deploy-web-to-gcs-cdn.md) |
62
+ | Netlify | `_redirects` or `netlify.toml` `/* /index.html 200` |
63
+
64
+ ## Provider guides
65
+
66
+ - [Deploy to GCP](deploy-to-gcp.md) — GCS + Cloud CDN (static web) + Cloud Run (backend)
67
+ - Deployment baseline — [seven requirements](../explanation/deployment-baseline.md)
68
+
69
+ For server-rendered web (future), see [Web SSR and admin SPA](https://github.com/FlourishHealth/terreno/blob/master/docs/implementationPlans/web-ssr-and-admin-spa.md).
@@ -0,0 +1,115 @@
1
+ # Deploy backend to Cloud Run
2
+
3
+ Deploy a Terreno `@terreno/api` backend (for example `example-backend`) to Google Cloud Run with Secret Manager.
4
+
5
+ Replace placeholders: `$PROJECT_ID`, `$REGION`, `$SERVICE_NAME`, `$REPOSITORY`.
6
+
7
+ ## Prerequisites
8
+
9
+ - [gcloud CLI](https://cloud.google.com/sdk/docs/install) installed and authenticated
10
+ - GCP project with billing enabled
11
+ - MongoDB Atlas cluster (or other replica set) — [deployment baseline](../explanation/deployment-baseline.md)
12
+ - Docker (local build) or Cloud Build
13
+
14
+ Enable APIs:
15
+
16
+ ```bash
17
+ gcloud services enable run.googleapis.com artifactregistry.googleapis.com secretmanager.googleapis.com --project="$PROJECT_ID"
18
+ ```
19
+
20
+ ## 1. Create Artifact Registry
21
+
22
+ ```bash
23
+ gcloud artifacts repositories create "$REPOSITORY" \
24
+ --repository-format=docker \
25
+ --location="$REGION" \
26
+ --project="$PROJECT_ID"
27
+ ```
28
+
29
+ ## 2. Build and push the image
30
+
31
+ From the **repository root** (the Dockerfile expects the monorepo context):
32
+
33
+ ```bash
34
+ docker build -f example-backend/Dockerfile -t "$REGION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$SERVICE_NAME:latest" .
35
+ docker push "$REGION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$SERVICE_NAME:latest"
36
+ ```
37
+
38
+ ## 3. Create secrets
39
+
40
+ Create Secret Manager secrets (values added out of band):
41
+
42
+ ```bash
43
+ for name in mongodb-uri token-secret token-issuer refresh-token-secret session-secret; do
44
+ gcloud secrets create "$SERVICE_NAME-$name" --project="$PROJECT_ID" --replication-policy=automatic
45
+ done
46
+ ```
47
+
48
+ Add secret values (example for MongoDB URI):
49
+
50
+ ```bash
51
+ echo -n 'mongodb+srv://user:pass@cluster.example/terreno?retryWrites=true&w=majority' | \
52
+ gcloud secrets versions add "$SERVICE_NAME-mongodb-uri" --data-file=- --project="$PROJECT_ID"
53
+ ```
54
+
55
+ Repeat for `TOKEN_SECRET`, `TOKEN_ISSUER`, `REFRESH_TOKEN_SECRET`, and `SESSION_SECRET`.
56
+
57
+ For Better Auth, also create `better-auth-secret` and set `AUTH_PROVIDER=better-auth` plus `BETTER_AUTH_URL` at deploy time. See [Configure Better Auth](configure-better-auth.md).
58
+
59
+ ## 4. Runtime service account
60
+
61
+ ```bash
62
+ gcloud iam service-accounts create "$SERVICE_NAME-runtime" --project="$PROJECT_ID"
63
+
64
+ gcloud projects add-iam-policy-binding "$PROJECT_ID" \
65
+ --member="serviceAccount:$SERVICE_NAME-runtime@$PROJECT_ID.iam.gserviceaccount.com" \
66
+ --role="roles/secretmanager.secretAccessor"
67
+ ```
68
+
69
+ Grant object access on your uploads bucket separately if using GCS file storage.
70
+
71
+ ## 5. Deploy to Cloud Run
72
+
73
+ ```bash
74
+ gcloud run deploy "$SERVICE_NAME" \
75
+ --image="$REGION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$SERVICE_NAME:latest" \
76
+ --region="$REGION" \
77
+ --project="$PROJECT_ID" \
78
+ --platform=managed \
79
+ --port=3000 \
80
+ --session-affinity \
81
+ --timeout=3600 \
82
+ --min-instances=1 \
83
+ --allow-unauthenticated \
84
+ --service-account="$SERVICE_NAME-runtime@$PROJECT_ID.iam.gserviceaccount.com" \
85
+ --set-secrets="MONGO_URI=$SERVICE_NAME-mongodb-uri:latest,TOKEN_SECRET=$SERVICE_NAME-token-secret:latest,TOKEN_ISSUER=$SERVICE_NAME-token-issuer:latest,REFRESH_TOKEN_SECRET=$SERVICE_NAME-refresh-token-secret:latest,SESSION_SECRET=$SERVICE_NAME-session-secret:latest" \
86
+ --set-env-vars="NODE_ENV=production"
87
+ ```
88
+
89
+ Adjust `min-instances` to `0` for dev sandboxes (websockets will churn on cold start).
90
+
91
+ ## 6. Verify
92
+
93
+ ```bash
94
+ SERVICE_URL=$(gcloud run services describe "$SERVICE_NAME" --region="$REGION" --project="$PROJECT_ID" --format='value(status.url)')
95
+ curl -s "$SERVICE_URL/health" | jq .
96
+ ```
97
+
98
+ Expect `"healthy": true`.
99
+
100
+ ## Production constraints
101
+
102
+ | Symptom | Cause | Fix |
103
+ |---------|-------|-----|
104
+ | Websockets disconnect every few requests | No session affinity on Cloud Run | Add `--session-affinity` |
105
+ | Socket connections drop after ~5 minutes | Default request timeout (300s) | Raise `--timeout` (for example `3600`) |
106
+ | Live feature flags / realtime never update; log mentions replica set | MongoDB is standalone, not a replica set | Use Atlas or `replSet` — change streams required (`feature-flags/src/featureFlagsApp.ts`) |
107
+ | First request after idle is slow; sockets reconnect constantly | Scaled to zero | Set `--min-instances=1` for user-facing services |
108
+ | Browser API calls blocked by CORS | `corsOrigin` / Better Auth `trustedOrigins` missing web origin | Add your CDN URL to backend CORS and auth config |
109
+
110
+ ## Related
111
+
112
+ - [Deployment baseline](../explanation/deployment-baseline.md)
113
+ - [Environment variables](../reference/environment-variables.md)
114
+ - [Deploy web to GCS + CDN](deploy-web-to-gcs-cdn.md)
115
+ - [GCP architecture](../explanation/deployment-architecture-gcp.md)
@@ -1,244 +1,36 @@
1
1
  # Deploy to Google Cloud Platform
2
2
 
3
- Learn how to deploy the Terreno demo and example-frontend apps to Google Cloud Storage with CDN-backed hosting.
3
+ Deploy a Terreno full-stack app to GCP: Cloud Run for the backend, GCS + Cloud CDN for the static web export.
4
4
 
5
- ## Prerequisites
5
+ ## Before you start
6
6
 
7
- Before you begin, ensure you have:
7
+ Read the [deployment baseline](../explanation/deployment-baseline.md) — seven requirements (replica-set MongoDB, auth secrets, build-time `EXPO_PUBLIC_API_URL`, and more) apply to every provider.
8
8
 
9
- - **GCP Project**: A Google Cloud Platform project with billing enabled
10
- - **gcloud CLI**: [Installed and authenticated](https://cloud.google.com/sdk/docs/install)
11
- - **Permissions**: Your GCP user or service account needs:
12
- - `roles/storage.admin` (create buckets, set IAM)
13
- - `roles/compute.loadBalancerAdmin` (create backend buckets, URL maps)
14
- - `roles/compute.networkAdmin` (create IPs, proxies, forwarding rules)
15
- - **GitHub Repository Access**: Admin access to configure secrets
9
+ ## Guides
16
10
 
17
- ## Initial Infrastructure Setup
11
+ | Guide | What it covers |
12
+ |-------|----------------|
13
+ | [Deploy backend to Cloud Run](deploy-backend-to-cloud-run.md) | Container image, Secret Manager, Cloud Run with session affinity |
14
+ | [Deploy web to GCS + CDN](deploy-web-to-gcs-cdn.md) | Static web export, bucket + CDN setup, cache invalidation |
15
+ | [Build for web](build-for-web.md) | Export command, `EXPO_PUBLIC_API_URL`, local verification |
18
16
 
19
- Run the setup script once to provision all GCP resources:
17
+ ## Architecture
20
18
 
21
- ``````bash
22
- # Clone the repository
23
- git clone https://github.com/FlourishHealth/terreno.git
24
- cd terreno
19
+ [GCP deployment architecture](../explanation/deployment-architecture-gcp.md) — topology diagram, component roles, and tradeoffs (Cloud Run vs GKE, static vs SSR).
25
20
 
26
- # Run the setup script
27
- ./scripts/setup-gcs-hosting.sh
28
- ``````
21
+ ## Scripts
29
22
 
30
- The script will prompt you for your service account email if `GCP_SA_KEY` is not set. It will create:
23
+ - [`scripts/setup-gcs-hosting.sh`](https://github.com/FlourishHealth/terreno/blob/master/scripts/setup-gcs-hosting.sh) — parameterized GCS + CDN provisioning for one site
31
24
 
32
- 1. **GCS Buckets**: `flourish-terreno-terreno-demo` and `flourish-terreno-terreno-frontend-example`
33
- 2. **Public Access**: Configured with `allUsers:objectViewer`
34
- 3. **SPA Routing**: `notFoundPage=index.html` for client-side routing
35
- 4. **CDN Resources**:
36
- - Backend buckets (CDN-enabled)
37
- - URL maps
38
- - Static IP addresses
39
- - HTTP proxies
40
- - Forwarding rules
25
+ ## Environment variables
41
26
 
42
- ### Script Output
27
+ [Environment variables reference](../reference/environment-variables.md) — full list of backend and client config.
43
28
 
44
- At the end, the script outputs:
29
+ ## Legacy Flourish deployment
45
30
 
46
- ``````
47
- === Setup Complete ===
31
+ Flourish-specific infrastructure (hardcoded project IDs, CI deploy workflows) lives in `infra/flourish/` and the existing `demo-deploy.yml` / `frontend-example-deploy.yml` workflows. New deployments should follow the generalized guides above with your own `$PROJECT_ID` and bucket names.
48
32
 
49
- Demo:
50
- CDN IP: 34.120.xxx.xxx
51
- URL: http://34.120.xxx.xxx/
52
- (Point your DNS A record to this IP)
33
+ ## Related
53
34
 
54
- Frontend Example:
55
- CDN IP: 34.149.xxx.xxx
56
- URL: http://34.149.xxx.xxx/
57
- (Point your DNS A record to this IP)
58
- ``````
59
-
60
- ## Configure GitHub Secrets
61
-
62
- Add the following secret to your GitHub repository:
63
-
64
- ### GCP_SA_KEY
65
-
66
- 1. Create a service account key:
67
- ``````bash
68
- # Create service account
69
- gcloud iam service-accounts create terreno-deploy \
70
- --display-name="Terreno Deploy"
71
-
72
- # Grant permissions
73
- gcloud projects add-iam-policy-binding flourish-terreno \
74
- --member="serviceAccount:terreno-deploy@flourish-terreno.iam.gserviceaccount.com" \
75
- --role="roles/storage.objectAdmin"
76
-
77
- gcloud projects add-iam-policy-binding flourish-terreno \
78
- --member="serviceAccount:terreno-deploy@flourish-terreno.iam.gserviceaccount.com" \
79
- --role="roles/compute.loadBalancerAdmin"
80
-
81
- # Create JSON key
82
- gcloud iam service-accounts keys create key.json \
83
- --iam-account=terreno-deploy@flourish-terreno.iam.gserviceaccount.com
84
- ``````
85
-
86
- 2. Add the key to GitHub:
87
- - Go to **Settings** → **Secrets and variables** → **Actions**
88
- - Click **New repository secret**
89
- - Name: `GCP_SA_KEY`
90
- - Value: Paste the entire contents of `key.json`
91
- - Click **Add secret**
92
-
93
- 3. Delete the local key file:
94
- ``````bash
95
- rm key.json
96
- ``````
97
-
98
- ## Deploy to Production
99
-
100
- Production deployments happen automatically when you push to the `master` branch:
101
-
102
- ``````bash
103
- # Make changes to demo or example-frontend
104
- git checkout master
105
- git pull
106
- # ... make changes ...
107
- git add .
108
- git commit -m "Update demo UI"
109
- git push origin master
110
- ``````
111
-
112
- The workflows will:
113
- 1. Build the app with Bun and Expo
114
- 2. Upload the build artifact
115
- 3. Sync assets to GCS with cache headers:
116
- - Hashed assets: `Cache-Control: public, max-age=31536000, immutable`
117
- - `index.html`: `Cache-Control: no-cache, no-store, must-revalidate`
118
- 4. Invalidate the CDN cache
119
-
120
- ### Triggered Workflows
121
-
122
- | App | Workflow | Triggers on paths |
123
- |-----|----------|-------------------|
124
- | Demo | `demo-deploy.yml` | `demo/**`, `ui/**` |
125
- | Example Frontend | `frontend-example-deploy.yml` | `example-frontend/**`, `ui/**`, `rtk/**` |
126
-
127
- ## Deploy PR Previews
128
-
129
- Pull request previews deploy automatically when you open a PR that modifies the relevant paths:
130
-
131
- ``````bash
132
- # Create a feature branch
133
- git checkout -b feature/new-component
134
-
135
- # Make changes
136
- # ... edit files ...
137
-
138
- git add .
139
- git commit -m "Add new component"
140
- git push origin feature/new-component
141
-
142
- # Open a pull request on GitHub
143
- ``````
144
-
145
- The workflow will:
146
- 1. Build the app with a preview-specific `baseUrl`
147
- 2. Deploy to `gs://BUCKET/_previews/pr-{number}/`
148
- 3. Create GitHub deployment with a preview URL
149
- 4. Comment on the PR with the preview link
150
-
151
- ### Preview URLs
152
-
153
- Previews are accessible at:
154
- - **Demo**: `http://{CDN_IP}/_previews/pr-{number}/` (or `https://storage.googleapis.com/flourish-terreno-terreno-demo/_previews/pr-{number}/` if CDN is not configured)
155
- - **Example Frontend**: `http://{CDN_IP}/_previews/pr-{number}/` (or `https://storage.googleapis.com/flourish-terreno-terreno-frontend-example/_previews/pr-{number}/`)
156
-
157
- ### Preview Cleanup
158
-
159
- When you close or merge a PR, the `preview-cleanup.yml` workflow automatically:
160
- - Deletes preview files from both buckets
161
- - Deactivates GitHub deployments
162
-
163
- ## Manual Deployment
164
-
165
- To deploy manually without GitHub Actions:
166
-
167
- ``````bash
168
- # Demo
169
- cd demo
170
- bun install
171
- bun run compile
172
- bun run export
173
- gsutil -m -h "Cache-Control:public, max-age=31536000, immutable" \
174
- rsync -r -d -x '.*\.html$' \
175
- dist/ gs://flourish-terreno-terreno-demo/
176
- gsutil -h "Cache-Control:no-cache, no-store, must-revalidate" \
177
- cp dist/index.html gs://flourish-terreno-terreno-demo/index.html
178
-
179
- # Invalidate CDN
180
- gcloud compute url-maps invalidate-cdn-cache terreno-demo-url-map \
181
- --path "/*" --async
182
-
183
- # Example Frontend
184
- cd example-frontend
185
- bun install
186
- bun run compile
187
- bun run export
188
- gsutil -m -h "Cache-Control:public, max-age=31536000, immutable" \
189
- rsync -r -d -x '.*\.html$' \
190
- dist/ gs://flourish-terreno-terreno-frontend-example/
191
- gsutil -h "Cache-Control:no-cache, no-store, must-revalidate" \
192
- cp dist/index.html gs://flourish-terreno-terreno-frontend-example/index.html
193
-
194
- # Invalidate CDN
195
- gcloud compute url-maps invalidate-cdn-cache terreno-frontend-example-url-map \
196
- --path "/*" --async
197
- ``````
198
-
199
- ## Troubleshooting
200
-
201
- ### Build Fails with "Module not found"
202
-
203
- **Problem**: Workspace dependencies not compiled.
204
-
205
- **Solution**: Run `bun run compile` in `ui/` and `rtk/` before building the app.
206
-
207
- ### Preview URL Returns 404
208
-
209
- **Problem**: CDN's `notFoundPage` serves root `index.html`, not the preview's.
210
-
211
- **Solution**: The deploy workflow uploads "bare" route objects. Check that the workflow completed successfully.
212
-
213
- ### CDN Shows Stale Content
214
-
215
- **Problem**: CDN cache not invalidated.
216
-
217
- **Solution**: Run cache invalidation manually:
218
- ``````bash
219
- gcloud compute url-maps invalidate-cdn-cache URLMAP_NAME --path "/*" --async
220
- ``````
221
-
222
- ### Permission Denied on gsutil
223
-
224
- **Problem**: Service account lacks permissions.
225
-
226
- **Solution**: Grant `roles/storage.objectAdmin`:
227
- ``````bash
228
- gsutil iam ch "serviceAccount:SA_EMAIL:objectAdmin" gs://BUCKET_NAME
229
- ``````
230
-
231
- ### SPA Routes Return 404 on Refresh
232
-
233
- **Problem**: Bucket not configured with `notFoundPage`.
234
-
235
- **Solution**: Run the setup script or manually configure:
236
- ``````bash
237
- gsutil web set -e index.html gs://BUCKET_NAME
238
- ``````
239
-
240
- ## Next Steps
241
-
242
- - [GCP Hosting Architecture](../explanation/gcp-hosting-architecture.md) — Understand the design
243
- - [Environment Variables Reference](../reference/environment-variables.md) — Configure runtime settings
244
- - [Set up CI/CD pipelines](../how-to/README.md) — Automate testing and deployment
35
+ - [Environment variables](../reference/environment-variables.md)
36
+ - [Deployment baseline](../explanation/deployment-baseline.md)
@@ -0,0 +1,183 @@
1
+ # Deploy web to GCS + CDN
2
+
3
+ Host a static Terreno web export on Google Cloud Storage with Cloud CDN.
4
+
5
+ Replace placeholders: `$PROJECT_ID`, `$REGION`, `$WEB_BUCKET`, `$SITE_NAME`, `$DOMAIN`.
6
+
7
+ ## Prerequisites
8
+
9
+ - [gcloud CLI](https://cloud.google.com/sdk/docs/install) installed and authenticated
10
+ - Backend deployed and CORS configured — see [Deploy backend to Cloud Run](deploy-backend-to-cloud-run.md)
11
+ - [Build for web](build-for-web.md) completed with the correct `EXPO_PUBLIC_API_URL`
12
+
13
+ ## 1. Build the web bundle
14
+
15
+ Set the API URL **before** export — it is inlined into the bundle:
16
+
17
+ ```bash
18
+ cd example-frontend
19
+ EXPO_PUBLIC_API_URL=https://api.example.com bun run export
20
+ ```
21
+
22
+ The export script is `bun expo export --platform web` (see `example-frontend/package.json`).
23
+
24
+ Output is in `dist/`.
25
+
26
+ ## 2. Enable the Compute Engine API
27
+
28
+ Cloud CDN and its global load-balancing resources require the Compute Engine API:
29
+
30
+ ```bash
31
+ gcloud services enable compute.googleapis.com --project="$PROJECT_ID"
32
+ ```
33
+
34
+ ## 3. Create the GCS bucket
35
+
36
+ ```bash
37
+ gsutil mb -p "$PROJECT_ID" -l "$REGION" "gs://$WEB_BUCKET/"
38
+ ```
39
+
40
+ ## 4. Allow public object reads
41
+
42
+ Cloud CDN must be able to serve the bucket's objects to unauthenticated visitors:
43
+
44
+ ```bash
45
+ gsutil iam ch allUsers:objectViewer "gs://$WEB_BUCKET"
46
+ ```
47
+
48
+ Do not grant `allUsers` a write role such as `objectAdmin`.
49
+
50
+ ## 5. Configure SPA routing
51
+
52
+ Client-side routes require `index.html` for unknown paths:
53
+
54
+ ```bash
55
+ gsutil web set -e index.html "gs://$WEB_BUCKET"
56
+ ```
57
+
58
+ Do not set `MainPageSuffix` — GCS 301 redirects break client-side routing.
59
+
60
+ ## 6. Upload the build
61
+
62
+ ```bash
63
+ gsutil -m -h "Cache-Control:public, max-age=31536000, immutable" \
64
+ rsync -r -d -x '.*\.html$' \
65
+ dist/ "gs://$WEB_BUCKET/"
66
+
67
+ gsutil -h "Cache-Control:no-cache, no-store, must-revalidate" \
68
+ cp dist/index.html "gs://$WEB_BUCKET/index.html"
69
+ ```
70
+
71
+ ## 7. Create HTTPS CDN resources
72
+
73
+ The load balancer serves the bucket over HTTPS only. A Google-managed certificate secures
74
+ the domain:
75
+
76
+ ```bash
77
+ # Backend bucket (CDN-enabled)
78
+ gcloud compute backend-buckets create "${SITE_NAME}-backend" \
79
+ --gcs-bucket-name="$WEB_BUCKET" \
80
+ --enable-cdn \
81
+ --no-negative-caching \
82
+ --project="$PROJECT_ID"
83
+
84
+ # URL map
85
+ gcloud compute url-maps create "${SITE_NAME}-url-map" \
86
+ --default-backend-bucket="${SITE_NAME}-backend" \
87
+ --project="$PROJECT_ID"
88
+
89
+ # Static IP
90
+ gcloud compute addresses create "${SITE_NAME}-ip" --global --project="$PROJECT_ID"
91
+
92
+ # Managed TLS certificate
93
+ gcloud compute ssl-certificates create "${SITE_NAME}-cert" \
94
+ --domains="$DOMAIN" \
95
+ --global \
96
+ --project="$PROJECT_ID"
97
+
98
+ # HTTPS proxy
99
+ gcloud compute target-https-proxies create "${SITE_NAME}-https-proxy" \
100
+ --url-map="${SITE_NAME}-url-map" \
101
+ --ssl-certificates="${SITE_NAME}-cert" \
102
+ --project="$PROJECT_ID"
103
+
104
+ # HTTPS forwarding rule
105
+ gcloud compute forwarding-rules create "${SITE_NAME}-https-forwarding-rule" \
106
+ --address="${SITE_NAME}-ip" \
107
+ --target-https-proxy="${SITE_NAME}-https-proxy" \
108
+ --global \
109
+ --ports=443 \
110
+ --project="$PROJECT_ID"
111
+ ```
112
+
113
+ ## 8. Redirect HTTP to HTTPS
114
+
115
+ Port 80 should redirect rather than serve the bundle. Without a listener there at all, `http://$DOMAIN` fails to connect instead of sending visitors to the secure URL.
116
+
117
+ `gcloud` exposes redirect behavior only through an imported spec, not through `url-maps create` flags:
118
+
119
+ ```bash
120
+ gcloud compute url-maps import "${SITE_NAME}-http-redirect-url-map" \
121
+ --global --project="$PROJECT_ID" --source=/dev/stdin <<SPEC
122
+ name: ${SITE_NAME}-http-redirect-url-map
123
+ defaultUrlRedirect:
124
+ httpsRedirect: true
125
+ redirectResponseCode: MOVED_PERMANENTLY_DEFAULT
126
+ SPEC
127
+
128
+ gcloud compute target-http-proxies create "${SITE_NAME}-http-proxy" \
129
+ --url-map="${SITE_NAME}-http-redirect-url-map" \
130
+ --project="$PROJECT_ID"
131
+
132
+ gcloud compute forwarding-rules create "${SITE_NAME}-forwarding-rule" \
133
+ --address="${SITE_NAME}-ip" \
134
+ --target-http-proxy="${SITE_NAME}-http-proxy" \
135
+ --global \
136
+ --ports=80 \
137
+ --project="$PROJECT_ID"
138
+ ```
139
+
140
+ Port 80 now only ever returns a 301; the bundle itself is served exclusively over TLS.
141
+
142
+ Or run the parameterized script, which provisions steps 7 and 8 in one pass:
143
+
144
+ ```bash
145
+ ./scripts/setup-gcs-hosting.sh \
146
+ --project "$PROJECT_ID" \
147
+ --site-name "$SITE_NAME" \
148
+ --bucket "$WEB_BUCKET" \
149
+ --domain "$DOMAIN"
150
+ ```
151
+
152
+ ## 9. Point DNS and wait for the certificate
153
+
154
+ ```bash
155
+ gcloud compute addresses describe "${SITE_NAME}-ip" --global \
156
+ --project="$PROJECT_ID" --format='value(address)'
157
+ ```
158
+
159
+ Create an A record for `$DOMAIN` pointing at that IP. Managed certificates only begin provisioning once DNS resolves to the load balancer, and can take up to about an hour to become active:
160
+
161
+ ```bash
162
+ gcloud compute ssl-certificates describe "${SITE_NAME}-cert" --global \
163
+ --project="$PROJECT_ID" --format='value(managed.status)'
164
+ ```
165
+
166
+ Wait for `ACTIVE` before sending traffic. Still `PROVISIONING` after an hour usually means the A record does not resolve to the reserved IP.
167
+
168
+ ## 10. Invalidate cache after deploy
169
+
170
+ ```bash
171
+ gcloud compute url-maps invalidate-cdn-cache "${SITE_NAME}-url-map" \
172
+ --path "/*" --async --project="$PROJECT_ID"
173
+ ```
174
+
175
+ ## Static-only path
176
+
177
+ This guide hosts the `expo export -p web` output as static files. Server-rendered web (SSR, API routes) requires Expo SDK ≥ 55 — see [Web SSR and admin SPA](https://github.com/FlourishHealth/terreno/blob/master/docs/implementationPlans/web-ssr-and-admin-spa.md).
178
+
179
+ ## Related
180
+
181
+ - [Build for web](build-for-web.md)
182
+ - [Deploy backend to Cloud Run](deploy-backend-to-cloud-run.md)
183
+ - [GCP architecture](../explanation/deployment-architecture-gcp.md)