@intentsolutionsio/supabase-pack 1.0.0 → 1.0.3

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 (133) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +73 -47
  3. package/package.json +4 -4
  4. package/skills/supabase-advanced-troubleshooting/SKILL.md +404 -200
  5. package/skills/supabase-advanced-troubleshooting/references/errors.md +11 -0
  6. package/skills/supabase-advanced-troubleshooting/references/evidence-collection-framework.md +34 -0
  7. package/skills/supabase-advanced-troubleshooting/references/examples.md +11 -0
  8. package/skills/supabase-advanced-troubleshooting/references/rls-edge-functions-realtime.md +363 -0
  9. package/skills/supabase-advanced-troubleshooting/references/systematic-isolation.md +56 -0
  10. package/skills/supabase-advanced-troubleshooting/references/timing-analysis.md +35 -0
  11. package/skills/supabase-architecture-variants/SKILL.md +395 -216
  12. package/skills/supabase-architecture-variants/references/errors.md +11 -0
  13. package/skills/supabase-architecture-variants/references/examples.md +12 -0
  14. package/skills/supabase-architecture-variants/references/serverless-and-multi-tenant.md +251 -0
  15. package/skills/supabase-architecture-variants/references/variant-a-monolith-(simple).md +44 -0
  16. package/skills/supabase-architecture-variants/references/variant-b-service-layer-(moderate).md +72 -0
  17. package/skills/supabase-architecture-variants/references/variant-c-microservice-(complex).md +81 -0
  18. package/skills/supabase-auth-storage-realtime-core/SKILL.md +471 -37
  19. package/skills/supabase-ci-integration/SKILL.md +315 -67
  20. package/skills/supabase-ci-integration/references/errors.md +10 -0
  21. package/skills/supabase-ci-integration/references/examples.md +36 -0
  22. package/skills/supabase-ci-integration/references/implementation.md +54 -0
  23. package/skills/supabase-common-errors/SKILL.md +320 -62
  24. package/skills/supabase-common-errors/references/errors.md +53 -0
  25. package/skills/supabase-common-errors/references/examples.md +23 -0
  26. package/skills/supabase-cost-tuning/SKILL.md +365 -131
  27. package/skills/supabase-cost-tuning/references/cost-estimation.md +34 -0
  28. package/skills/supabase-cost-tuning/references/cost-reduction-strategies.md +40 -0
  29. package/skills/supabase-cost-tuning/references/errors.md +11 -0
  30. package/skills/supabase-cost-tuning/references/examples.md +15 -0
  31. package/skills/supabase-data-handling/SKILL.md +378 -145
  32. package/skills/supabase-data-handling/references/errors.md +11 -0
  33. package/skills/supabase-data-handling/references/examples.md +27 -0
  34. package/skills/supabase-data-handling/references/implementation.md +223 -0
  35. package/skills/supabase-data-handling/references/retention-and-backup.md +221 -0
  36. package/skills/supabase-debug-bundle/SKILL.md +267 -73
  37. package/skills/supabase-debug-bundle/references/errors.md +12 -0
  38. package/skills/supabase-debug-bundle/references/examples.md +24 -0
  39. package/skills/supabase-debug-bundle/references/implementation.md +54 -0
  40. package/skills/supabase-deploy-integration/SKILL.md +258 -147
  41. package/skills/supabase-deploy-integration/references/errors.md +11 -0
  42. package/skills/supabase-deploy-integration/references/examples.md +21 -0
  43. package/skills/supabase-deploy-integration/references/google-cloud-run.md +36 -0
  44. package/skills/supabase-deploy-integration/references/vercel-deployment.md +35 -0
  45. package/skills/supabase-enterprise-rbac/SKILL.md +327 -160
  46. package/skills/supabase-enterprise-rbac/references/api-scoping-and-enforcement.md +255 -0
  47. package/skills/supabase-enterprise-rbac/references/errors.md +11 -0
  48. package/skills/supabase-enterprise-rbac/references/examples.md +12 -0
  49. package/skills/supabase-enterprise-rbac/references/role-implementation.md +33 -0
  50. package/skills/supabase-enterprise-rbac/references/sso-integration.md +35 -0
  51. package/skills/supabase-hello-world/SKILL.md +160 -54
  52. package/skills/supabase-incident-runbook/SKILL.md +453 -131
  53. package/skills/supabase-incident-runbook/references/errors.md +11 -0
  54. package/skills/supabase-incident-runbook/references/examples.md +10 -0
  55. package/skills/supabase-incident-runbook/references/immediate-actions-by-error-type.md +41 -0
  56. package/skills/supabase-install-auth/SKILL.md +186 -50
  57. package/skills/supabase-install-auth/references/examples.md +102 -0
  58. package/skills/supabase-known-pitfalls/SKILL.md +411 -241
  59. package/skills/supabase-known-pitfalls/references/errors.md +11 -0
  60. package/skills/supabase-known-pitfalls/references/examples.md +12 -0
  61. package/skills/supabase-load-scale/SKILL.md +346 -217
  62. package/skills/supabase-load-scale/references/capacity-planning.md +47 -0
  63. package/skills/supabase-load-scale/references/errors.md +11 -0
  64. package/skills/supabase-load-scale/references/examples.md +26 -0
  65. package/skills/supabase-load-scale/references/load-testing-with-k6.md +59 -0
  66. package/skills/supabase-load-scale/references/scaling-patterns.md +65 -0
  67. package/skills/supabase-load-scale/references/table-partitioning.md +263 -0
  68. package/skills/supabase-local-dev-loop/SKILL.md +272 -73
  69. package/skills/supabase-local-dev-loop/references/errors.md +11 -0
  70. package/skills/supabase-local-dev-loop/references/examples.md +21 -0
  71. package/skills/supabase-local-dev-loop/references/implementation.md +60 -0
  72. package/skills/supabase-migration-deep-dive/SKILL.md +338 -177
  73. package/skills/supabase-migration-deep-dive/references/backfill-versioning-rollback.md +258 -0
  74. package/skills/supabase-migration-deep-dive/references/errors.md +11 -0
  75. package/skills/supabase-migration-deep-dive/references/examples.md +12 -0
  76. package/skills/supabase-migration-deep-dive/references/implementation-plan.md +80 -0
  77. package/skills/supabase-migration-deep-dive/references/pre-migration-assessment.md +39 -0
  78. package/skills/supabase-multi-env-setup/SKILL.md +393 -152
  79. package/skills/supabase-multi-env-setup/references/configuration-structure.md +59 -0
  80. package/skills/supabase-multi-env-setup/references/errors.md +11 -0
  81. package/skills/supabase-multi-env-setup/references/examples.md +11 -0
  82. package/skills/supabase-observability/SKILL.md +318 -196
  83. package/skills/supabase-observability/references/alert-configuration.md +40 -0
  84. package/skills/supabase-observability/references/errors.md +11 -0
  85. package/skills/supabase-observability/references/examples.md +13 -0
  86. package/skills/supabase-observability/references/metrics-collection.md +65 -0
  87. package/skills/supabase-performance-tuning/SKILL.md +304 -160
  88. package/skills/supabase-performance-tuning/references/caching-strategy.md +49 -0
  89. package/skills/supabase-performance-tuning/references/errors.md +11 -0
  90. package/skills/supabase-performance-tuning/references/examples.md +13 -0
  91. package/skills/supabase-policy-guardrails/SKILL.md +248 -221
  92. package/skills/supabase-policy-guardrails/references/ci-cost-security.md +484 -0
  93. package/skills/supabase-policy-guardrails/references/errors.md +11 -0
  94. package/skills/supabase-policy-guardrails/references/eslint-rules.md +46 -0
  95. package/skills/supabase-policy-guardrails/references/examples.md +10 -0
  96. package/skills/supabase-prod-checklist/SKILL.md +474 -84
  97. package/skills/supabase-prod-checklist/references/errors.md +63 -0
  98. package/skills/supabase-prod-checklist/references/examples.md +153 -0
  99. package/skills/supabase-prod-checklist/references/implementation.md +113 -0
  100. package/skills/supabase-rate-limits/SKILL.md +311 -98
  101. package/skills/supabase-rate-limits/references/errors.md +11 -0
  102. package/skills/supabase-rate-limits/references/examples.md +46 -0
  103. package/skills/supabase-rate-limits/references/implementation.md +66 -0
  104. package/skills/supabase-reference-architecture/SKILL.md +249 -182
  105. package/skills/supabase-reference-architecture/references/errors.md +29 -0
  106. package/skills/supabase-reference-architecture/references/examples.md +116 -0
  107. package/skills/supabase-reference-architecture/references/key-components.md +244 -0
  108. package/skills/supabase-reference-architecture/references/project-structure.md +109 -0
  109. package/skills/supabase-reliability-patterns/SKILL.md +229 -234
  110. package/skills/supabase-reliability-patterns/references/circuit-breaker.md +36 -0
  111. package/skills/supabase-reliability-patterns/references/dead-letter-queue.md +48 -0
  112. package/skills/supabase-reliability-patterns/references/errors.md +11 -0
  113. package/skills/supabase-reliability-patterns/references/examples.md +11 -0
  114. package/skills/supabase-reliability-patterns/references/idempotency-keys.md +36 -0
  115. package/skills/supabase-reliability-patterns/references/offline-degradation-health-dualwrite.md +489 -0
  116. package/skills/supabase-schema-from-requirements/SKILL.md +373 -34
  117. package/skills/supabase-sdk-patterns/SKILL.md +388 -99
  118. package/skills/supabase-sdk-patterns/references/errors.md +11 -0
  119. package/skills/supabase-sdk-patterns/references/examples.md +45 -0
  120. package/skills/supabase-sdk-patterns/references/implementation.md +67 -0
  121. package/skills/supabase-security-basics/SKILL.md +282 -102
  122. package/skills/supabase-security-basics/references/errors.md +10 -0
  123. package/skills/supabase-security-basics/references/examples.md +70 -0
  124. package/skills/supabase-security-basics/references/implementation.md +39 -0
  125. package/skills/supabase-upgrade-migration/SKILL.md +248 -66
  126. package/skills/supabase-upgrade-migration/references/errors.md +10 -0
  127. package/skills/supabase-upgrade-migration/references/examples.md +51 -0
  128. package/skills/supabase-upgrade-migration/references/implementation.md +29 -0
  129. package/skills/supabase-webhooks-events/SKILL.md +412 -138
  130. package/skills/supabase-webhooks-events/references/errors.md +55 -0
  131. package/skills/supabase-webhooks-events/references/event-handler-pattern.md +106 -0
  132. package/skills/supabase-webhooks-events/references/examples.md +133 -0
  133. package/skills/supabase-webhooks-events/references/signature-verification.md +165 -0
@@ -1,222 +1,463 @@
1
1
  ---
2
2
  name: supabase-multi-env-setup
3
- description: |
4
- Configure Supabase across development, staging, and production environments.
5
- Use when setting up multi-environment deployments, configuring per-environment secrets,
6
- or implementing environment-specific Supabase configurations.
7
- Trigger with phrases like "supabase environments", "supabase staging",
8
- "supabase dev prod", "supabase environment setup", "supabase config by env".
9
- allowed-tools: Read, Write, Edit, Bash(aws:*), Bash(gcloud:*), Bash(vault:*)
3
+ description: 'Configure Supabase across development, staging, and production with
4
+ separate projects,
5
+
6
+ environment-specific secrets, and safe migration promotion.
7
+
8
+ Use when setting up multi-environment deployments, isolating dev from prod data,
9
+
10
+ configuring per-environment Supabase projects, or promoting migrations through environments.
11
+
12
+ Trigger: "supabase environments", "supabase staging", "supabase dev prod",
13
+
14
+ "supabase multi-project", "supabase env config", "database branching".
15
+
16
+ '
17
+ allowed-tools: Read, Write, Edit, Bash(npx supabase:*), Bash(supabase:*), Bash(vercel:*),
18
+ Grep, Glob
10
19
  version: 1.0.0
11
20
  license: MIT
12
21
  author: Jeremy Longshore <jeremy@intentsolutions.io>
22
+ tags:
23
+ - saas
24
+ - supabase
25
+ - deployment
26
+ - environments
27
+ - multi-env
28
+ - devops
29
+ compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw
13
30
  ---
14
-
15
31
  # Supabase Multi-Environment Setup
16
32
 
17
33
  ## Overview
18
- Configure Supabase across development, staging, and production environments.
34
+
35
+ Production Supabase deployments require separate projects per environment — each with its own URL, API keys, database, and RLS policies. This skill configures a three-tier environment architecture (local dev, staging, production) with safe migration promotion via `supabase db push`, environment-aware `createClient` initialization, database branching for preview deployments, and CI/CD pipelines that prevent accidental cross-environment operations.
36
+
37
+ **When to use:** Setting up a new project with multiple environments, migrating from a single-project setup to multi-env, adding staging to an existing dev/prod split, or configuring preview environments with database branching.
19
38
 
20
39
  ## Prerequisites
21
- - Separate Supabase accounts or API keys per environment
22
- - Secret management solution (Vault, AWS Secrets Manager, etc.)
23
- - CI/CD pipeline with environment variables
24
- - Environment detection in application
25
40
 
26
- ## Environment Strategy
41
+ - Three separate Supabase projects created at [supabase.com/dashboard](https://supabase.com/dashboard) (dev, staging, production)
42
+ - Supabase CLI installed: `npm install -g supabase` or `npx supabase --version`
43
+ - `@supabase/supabase-js` v2+ installed in your project
44
+ - Node.js 18+ with framework that supports `.env` files (Next.js, Nuxt, SvelteKit, etc.)
45
+ - A secret management solution for CI (GitHub Actions Secrets, Vercel env vars, etc.)
46
+
47
+ ## Instructions
48
+
49
+ ### Step 1: Environment Files and Project Layout
27
50
 
28
- | Environment | Purpose | API Keys | Data |
29
- |-------------|---------|----------|------|
30
- | Development | Local dev | Test keys | Sandbox |
31
- | Staging | Pre-prod validation | Staging keys | Test data |
32
- | Production | Live traffic | Production keys | Real data |
51
+ Create one Supabase CLI project with shared migrations and per-environment credential files. Each `.env.*` file points to a different Supabase project.
33
52
 
34
- ## Configuration Structure
53
+ **Project structure:**
35
54
 
36
55
  ```
37
- config/
56
+ my-app/
38
57
  ├── supabase/
39
- │ ├── base.json # Shared config
40
- │ ├── development.json # Dev overrides
41
- ├── staging.json # Staging overrides
42
- └── production.json # Prod overrides
43
- ```
44
-
45
- ### base.json
46
- ```json
47
- {
48
- "timeout": 30000,
49
- "retries": 3,
50
- "cache": {
51
- "enabled": true,
52
- "ttlSeconds": 60
53
- }
54
- }
58
+ │ ├── config.toml # Local CLI config
59
+ │ ├── migrations/ # Shared migrations (all envs use the same schema)
60
+ │ └── 20260101000000_initial.sql
61
+ ├── seed.sql # Dev-only seed data (runs on db reset only)
62
+ │ └── functions/ # Edge Functions (deployed per env)
63
+ ├── .env.local # Local dev → supabase start
64
+ ├── .env.staging # Staging project credentials
65
+ ├── .env.production # Production project credentials
66
+ └── .gitignore # Must include .env.staging, .env.production
55
67
  ```
56
68
 
57
- ### development.json
58
- ```json
59
- {
60
- "apiKey": "${SUPABASE_API_KEY}",
61
- "baseUrl": "https://api-sandbox.supabase.com",
62
- "debug": true,
63
- "cache": {
64
- "enabled": false
65
- }
66
- }
69
+ **Environment files:**
70
+
71
+ ```bash
72
+ # .env.local — local development (safe defaults from supabase start)
73
+ NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
74
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0
75
+ SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU
76
+ DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/postgres
77
+ SUPABASE_ENV=local
78
+
79
+ # .env.staging — staging project
80
+ NEXT_PUBLIC_SUPABASE_URL=https://<staging-ref>.supabase.co
81
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...staging-anon-key
82
+ SUPABASE_SERVICE_ROLE_KEY=eyJ...staging-service-key
83
+ DATABASE_URL=postgres://postgres.<staging-ref>:<password>@aws-0-<region>.pooler.supabase.com:6543/postgres
84
+ SUPABASE_ENV=staging
85
+
86
+ # .env.production — production project (NEVER commit this file)
87
+ NEXT_PUBLIC_SUPABASE_URL=https://<prod-ref>.supabase.co
88
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...prod-anon-key
89
+ SUPABASE_SERVICE_ROLE_KEY=eyJ...prod-service-key
90
+ DATABASE_URL=postgres://postgres.<prod-ref>:<password>@aws-0-<region>.pooler.supabase.com:6543/postgres
91
+ SUPABASE_ENV=production
67
92
  ```
68
93
 
69
- ### staging.json
70
- ```json
71
- {
72
- "apiKey": "${SUPABASE_API_KEY_STAGING}",
73
- "baseUrl": "https://api-staging.supabase.com",
74
- "debug": false
75
- }
94
+ **Critical `.gitignore` entries:**
95
+
96
+ ```gitignore
97
+ .env.staging
98
+ .env.production
99
+ # .env.local is safe to commit (contains only local dev keys)
76
100
  ```
77
101
 
78
- ### production.json
79
- ```json
80
- {
81
- "apiKey": "${SUPABASE_API_KEY_PROD}",
82
- "baseUrl": "https://api.supabase.com",
83
- "debug": false,
84
- "retries": 5
85
- }
102
+ **Link each environment to the CLI:**
103
+
104
+ ```text
105
+ # Local development
106
+ npx supabase start
107
+
108
+ # Link staging (stores ref in supabase/.temp/project-ref)
109
+ npx supabase link --project-ref <staging-ref>
110
+
111
+ # Link production (re-links, overwriting staging ref)
112
+ npx supabase link --project-ref <prod-ref>
86
113
  ```
87
114
 
88
- ## Environment Detection
115
+ > **Note:** The CLI can only link one project at a time. Switch between environments by re-running `supabase link` with the target project ref before any `db push` or `functions deploy` operation.
116
+
117
+ ### Step 2: Environment-Aware Client and Safeguards
118
+
119
+ Build a `createClient` wrapper that selects the correct URL and keys based on the active environment, plus production safeguards that block destructive operations.
120
+
121
+ **Environment detection (`lib/env.ts`):**
89
122
 
90
123
  ```typescript
91
- // src/supabase/config.ts
92
- import baseConfig from '../../config/supabase/base.json';
124
+ export type Environment = 'local' | 'staging' | 'production';
93
125
 
94
- type Environment = 'development' | 'staging' | 'production';
126
+ export function getEnvironment(): Environment {
127
+ // Explicit env var takes priority
128
+ const explicit = process.env.SUPABASE_ENV;
129
+ if (explicit === 'local' || explicit === 'staging' || explicit === 'production') {
130
+ return explicit;
131
+ }
95
132
 
96
- function detectEnvironment(): Environment {
97
- const env = process.env.NODE_ENV || 'development';
98
- const validEnvs: Environment[] = ['development', 'staging', 'production'];
99
- return validEnvs.includes(env as Environment)
100
- ? (env as Environment)
101
- : 'development';
133
+ // Fallback: detect from URL
134
+ const url = process.env.NEXT_PUBLIC_SUPABASE_URL ?? '';
135
+ if (url.includes('127.0.0.1') || url.includes('localhost')) return 'local';
136
+ if (url.includes('staging')) return 'staging';
137
+ return 'production';
102
138
  }
103
139
 
104
- export function getSupabaseConfig() {
105
- const env = detectEnvironment();
106
- const envConfig = require(`../../config/supabase/${env}.json`);
140
+ export function isProduction(): boolean {
141
+ return getEnvironment() === 'production';
142
+ }
107
143
 
108
- return {
109
- ...baseConfig,
110
- ...envConfig,
111
- environment: env,
112
- };
144
+ export function requireNonProduction(operation: string): void {
145
+ if (isProduction()) {
146
+ throw new Error(
147
+ `[BLOCKED] "${operation}" is not allowed in production. ` +
148
+ `Current SUPABASE_ENV=${process.env.SUPABASE_ENV}`
149
+ );
150
+ }
113
151
  }
114
152
  ```
115
153
 
116
- ## Secret Management by Environment
154
+ **Supabase client factory (`lib/supabase.ts`):**
117
155
 
118
- ### Local Development
119
- ```bash
120
- # .env.local (git-ignored)
121
- SUPABASE_API_KEY=sk_test_dev_***
156
+ ```typescript
157
+ import { createClient, type SupabaseClient } from '@supabase/supabase-js';
158
+ import type { Database } from './database.types';
159
+ import { getEnvironment } from './env';
160
+
161
+ // Browser client (uses anon key, respects RLS)
162
+ export function createBrowserClient(): SupabaseClient<Database> {
163
+ const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
164
+ const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
165
+
166
+ return createClient<Database>(supabaseUrl, supabaseAnonKey, {
167
+ auth: {
168
+ autoRefreshToken: true,
169
+ persistSession: true,
170
+ },
171
+ global: {
172
+ headers: { 'x-environment': getEnvironment() },
173
+ },
174
+ });
175
+ }
176
+
177
+ // Server client (uses service role key, bypasses RLS)
178
+ export function createServerClient(): SupabaseClient<Database> {
179
+ const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
180
+ const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY!;
181
+
182
+ return createClient<Database>(supabaseUrl, serviceRoleKey, {
183
+ auth: {
184
+ autoRefreshToken: false,
185
+ persistSession: false,
186
+ },
187
+ });
188
+ }
122
189
  ```
123
190
 
124
- ### CI/CD (GitHub Actions)
125
- ```yaml
126
- env:
127
- SUPABASE_API_KEY: ${{ secrets.SUPABASE_API_KEY_${{ matrix.environment }} }}
191
+ **Production safeguards:**
192
+
193
+ ```typescript
194
+ import { requireNonProduction } from './env';
195
+ import { createServerClient } from './supabase';
196
+
197
+ // Seed data — only runs in local/staging
198
+ export async function seedTestData(): Promise<void> {
199
+ requireNonProduction('seedTestData');
200
+ const supabase = createServerClient();
201
+ await supabase.from('test_users').insert([
202
+ { email: 'test@example.com', role: 'admin' },
203
+ { email: 'user@example.com', role: 'member' },
204
+ ]);
205
+ }
206
+
207
+ // Destructive reset — only runs in local
208
+ export async function resetDatabase(): Promise<void> {
209
+ requireNonProduction('resetDatabase');
210
+ const supabase = createServerClient();
211
+ await supabase.rpc('truncate_all_tables');
212
+ }
128
213
  ```
129
214
 
130
- ### Production (Vault/Secrets Manager)
131
- ```bash
132
- # AWS Secrets Manager
133
- aws secretsmanager get-secret-value --secret-id supabase/production/api-key
215
+ **Environment-specific RLS policies:**
134
216
 
135
- # GCP Secret Manager
136
- gcloud secrets versions access latest --secret=supabase-api-key
217
+ ```sql
218
+ -- supabase/migrations/20260115000000_env_rls.sql
219
+ -- Allow broader access in staging for QA testing
220
+ CREATE POLICY "staging_read_all" ON public.profiles
221
+ FOR SELECT
222
+ USING (
223
+ current_setting('app.environment', true) = 'staging'
224
+ OR auth.uid() = id
225
+ );
137
226
 
138
- # HashiCorp Vault
139
- vault kv get -field=api_key secret/supabase/production
227
+ -- Set environment in each request via the x-environment header
228
+ -- or via a Postgres config parameter in your connection string
140
229
  ```
141
230
 
142
- ## Environment Isolation
231
+ ### Step 3: Migration Promotion and Database Branching
143
232
 
144
- ```typescript
145
- // Prevent production operations in non-prod
146
- function guardProductionOperation(operation: string): void {
147
- const config = getSupabaseConfig();
233
+ Promote migrations through environments (local -> staging -> production) and use database branching for preview deployments.
148
234
 
149
- if (config.environment !== 'production') {
150
- console.warn(`[supabase] ${operation} blocked in ${config.environment}`);
151
- throw new Error(`${operation} only allowed in production`);
152
- }
153
- }
235
+ **Migration promotion workflow:**
154
236
 
155
- // Usage
156
- async function deleteAllData() {
157
- guardProductionOperation('deleteAllData');
158
- // Dangerous operation here
159
- }
237
+ ```text
238
+ # 1. Create migration locally
239
+ npx supabase migration new add_profiles_table
240
+ # Edit: supabase/migrations/20260120000000_add_profiles_table.sql
241
+
242
+ # 2. Test locally with full reset
243
+ npx supabase db reset # Applies all migrations + seed.sql
244
+ npx supabase test db # Run pgTAP tests if configured
245
+
246
+ # 3. Push to staging
247
+ npx supabase link --project-ref <staging-ref>
248
+ npx supabase db push # Applies only new migrations
249
+ # Run integration tests against staging URL
250
+
251
+ # 4. Push to production (after staging verification)
252
+ npx supabase link --project-ref <prod-ref>
253
+ npx supabase db push # Same migrations, production database
254
+ # Verify with health check endpoint
255
+
256
+ # 5. Generate types from the canonical source
257
+ npx supabase gen types typescript --local > lib/database.types.ts
258
+ # Or from linked project:
259
+ # npx supabase gen types typescript --linked > lib/database.types.ts
160
260
  ```
161
261
 
162
- ## Feature Flags by Environment
262
+ **Database branching for preview environments:**
163
263
 
164
- ```typescript
165
- const featureFlags: Record<Environment, Record<string, boolean>> = {
166
- development: {
167
- newFeature: true,
168
- betaApi: true,
169
- },
170
- staging: {
171
- newFeature: true,
172
- betaApi: false,
173
- },
174
- production: {
175
- newFeature: false,
176
- betaApi: false,
177
- },
178
- };
264
+ ```text
265
+ # Create a branch for a feature (requires Supabase Pro plan)
266
+ npx supabase branches create feature-user-profiles \
267
+ --project-ref <staging-ref>
268
+
269
+ # Each branch gets its own:
270
+ # - Database with current migrations applied
271
+ # - Unique API URL and keys
272
+ # - Isolated storage buckets
273
+
274
+ # List active branches
275
+ npx supabase branches list --project-ref <staging-ref>
276
+
277
+ # Connect preview deployment to the branch
278
+ # In your CI (e.g., Vercel preview deploys):
279
+ NEXT_PUBLIC_SUPABASE_URL=https://<branch-ref>.supabase.co
280
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=<branch-anon-key>
281
+
282
+ # Delete branch after merge
283
+ npx supabase branches delete feature-user-profiles \
284
+ --project-ref <staging-ref>
179
285
  ```
180
286
 
181
- ## Instructions
287
+ **CI/CD per-environment deployment (`.github/workflows/deploy.yml`):**
182
288
 
183
- ### Step 1: Create Config Structure
184
- Set up the base and per-environment configuration files.
289
+ ```yaml
290
+ name: Deploy Supabase
291
+ on:
292
+ push:
293
+ branches: [develop, main]
294
+
295
+ jobs:
296
+ deploy-staging:
297
+ if: github.ref == 'refs/heads/develop'
298
+ runs-on: ubuntu-latest
299
+ steps:
300
+ - uses: actions/checkout@v4
301
+ - uses: supabase/setup-cli@v1
302
+ with:
303
+ version: latest
304
+ - name: Push migrations to staging
305
+ run: |
306
+ npx supabase link --project-ref ${{ secrets.STAGING_PROJECT_REF }}
307
+ npx supabase db push
308
+ env:
309
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
310
+ SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }}
311
+ - name: Deploy Edge Functions
312
+ run: npx supabase functions deploy --project-ref ${{ secrets.STAGING_PROJECT_REF }}
313
+ env:
314
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
315
+
316
+ deploy-production:
317
+ if: github.ref == 'refs/heads/main'
318
+ runs-on: ubuntu-latest
319
+ environment: production # Requires approval in GitHub
320
+ steps:
321
+ - uses: actions/checkout@v4
322
+ - uses: supabase/setup-cli@v1
323
+ with:
324
+ version: latest
325
+ - name: Push migrations to production
326
+ run: |
327
+ npx supabase link --project-ref ${{ secrets.PROD_PROJECT_REF }}
328
+ npx supabase db push
329
+ env:
330
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
331
+ SUPABASE_DB_PASSWORD: ${{ secrets.PROD_DB_PASSWORD }}
332
+ - name: Deploy Edge Functions
333
+ run: npx supabase functions deploy --project-ref ${{ secrets.PROD_PROJECT_REF }}
334
+ env:
335
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
336
+ ```
185
337
 
186
- ### Step 2: Implement Environment Detection
187
- Add logic to detect and load environment-specific config.
338
+ **Environment-specific seed data:**
188
339
 
189
- ### Step 3: Configure Secrets
190
- Store API keys securely using your secret management solution.
340
+ ```sql
341
+ -- supabase/seed.sql (runs ONLY on `supabase db reset`, never in production)
342
+ INSERT INTO public.profiles (id, email, role) VALUES
343
+ ('00000000-0000-0000-0000-000000000001', 'admin@test.local', 'admin'),
344
+ ('00000000-0000-0000-0000-000000000002', 'user@test.local', 'member');
191
345
 
192
- ### Step 4: Add Environment Guards
193
- Implement safeguards for production-only operations.
346
+ -- Insert test data for local development
347
+ INSERT INTO public.projects (name, owner_id) VALUES
348
+ ('Test Project', '00000000-0000-0000-0000-000000000001');
349
+ ```
194
350
 
195
351
  ## Output
196
- - Multi-environment config structure
197
- - Environment detection logic
198
- - Secure secret management
199
- - Production safeguards enabled
352
+
353
+ After completing this skill, you will have:
354
+
355
+ - **Three isolated Supabase projects** — each environment has its own URL, API keys, database, and storage
356
+ - **Environment-specific `.env` files** — `.env.local`, `.env.staging`, `.env.production` with correct credentials
357
+ - **Environment-aware `createClient`** — browser and server clients auto-configured from env vars with `x-environment` header tracking
358
+ - **Production safeguards** — `requireNonProduction()` guard blocks destructive operations outside local/staging
359
+ - **Migration promotion pipeline** — `supabase db push` promotes schema changes local -> staging -> production
360
+ - **Database branching** — preview environments get isolated database branches (Pro plan)
361
+ - **CI/CD workflows** — GitHub Actions deploys migrations and Edge Functions per environment with approval gates for production
362
+ - **Generated TypeScript types** — `database.types.ts` generated from local or linked project schema
200
363
 
201
364
  ## Error Handling
202
- | Issue | Cause | Solution |
365
+
366
+ | Error | Cause | Solution |
203
367
  |-------|-------|----------|
204
- | Wrong environment | Missing NODE_ENV | Set environment variable |
205
- | Secret not found | Wrong secret path | Verify secret manager config |
206
- | Config merge fails | Invalid JSON | Validate config files |
207
- | Production guard triggered | Wrong environment | Check NODE_ENV value |
368
+ | `Cannot find project ref` | CLI not linked to a project | Run `npx supabase link --project-ref <ref>` before `db push` |
369
+ | `Migration has already been applied` | Re-running an existing migration | Check `supabase_migrations.schema_migrations` table; migrations are idempotent by ref |
370
+ | `Permission denied for schema public` | Wrong database password | Verify `SUPABASE_DB_PASSWORD` matches the project's database password in dashboard |
371
+ | `Seed data appeared in production` | Ran `supabase db reset` on prod | `seed.sql` only runs on `db reset` — never reset production; use `db push` instead |
372
+ | `Wrong environment keys in client` | `.env` file mismatch | Check `SUPABASE_ENV` var and verify URL matches expected project ref |
373
+ | `Branch creation failed` | Free plan or branching not enabled | Database branching requires Supabase Pro plan; enable in project settings |
374
+ | `Migration drift between envs` | Skipped staging promotion | Always promote through staging first; compare with `supabase migration list` per project |
375
+ | `Type generation mismatch` | Types generated from wrong env | Regenerate from local (`--local`) or re-link to the canonical environment |
208
376
 
209
377
  ## Examples
210
378
 
211
- ### Quick Environment Check
379
+ **Example 1 — Quick three-env bootstrap:**
380
+
381
+ ```bash
382
+ # Initialize Supabase in existing project
383
+ npx supabase init
384
+
385
+ # Start local
386
+ npx supabase start
387
+ # Copy output keys to .env.local
388
+
389
+ # Create staging + production projects in dashboard
390
+ # Copy their URLs and keys to .env.staging / .env.production
391
+
392
+ # Create first migration
393
+ npx supabase migration new create_users
394
+ # Edit the migration, then:
395
+ npx supabase db reset # Test locally
396
+
397
+ # Promote to staging
398
+ npx supabase link --project-ref abcdefghijklmnop
399
+ npx supabase db push
400
+
401
+ # Promote to production
402
+ npx supabase link --project-ref qrstuvwxyz123456
403
+ npx supabase db push
404
+ ```
405
+
406
+ **Example 2 — Next.js middleware for environment validation:**
407
+
408
+ ```typescript
409
+ // middleware.ts
410
+ import { NextResponse } from 'next/server';
411
+ import type { NextRequest } from 'next/server';
412
+
413
+ export function middleware(request: NextRequest) {
414
+ const response = NextResponse.next();
415
+
416
+ // Add environment header for observability
417
+ const env = process.env.SUPABASE_ENV ?? 'unknown';
418
+ response.headers.set('x-supabase-env', env);
419
+
420
+ // Block admin routes in production unless authenticated
421
+ if (env === 'production' && request.nextUrl.pathname.startsWith('/admin/seed')) {
422
+ return NextResponse.json({ error: 'Not available in production' }, { status: 403 });
423
+ }
424
+
425
+ return response;
426
+ }
427
+ ```
428
+
429
+ **Example 3 — Verify environment before destructive operations:**
430
+
212
431
  ```typescript
213
- const env = getSupabaseConfig();
214
- console.log(`Running in ${env.environment} with ${env.baseUrl}`);
432
+ import { getEnvironment, requireNonProduction } from '@/lib/env';
433
+
434
+ async function adminResetHandler(req: Request) {
435
+ const env = getEnvironment();
436
+ console.log(`[admin-reset] Running in ${env} environment`);
437
+
438
+ requireNonProduction('admin-reset');
439
+
440
+ // Safe to proceed — we're in local or staging
441
+ const { error } = await supabase.rpc('reset_test_data');
442
+ if (error) throw error;
443
+
444
+ return Response.json({ status: 'reset complete', environment: env });
445
+ }
215
446
  ```
216
447
 
217
448
  ## Resources
218
- - [Supabase Environments Guide](https://supabase.com/docs/environments)
219
- - [12-Factor App Config](https://12factor.net/config)
449
+
450
+ - [Managing Environments — Supabase Docs](https://supabase.com/docs/guides/deployment/managing-environments)
451
+ - [Database Migrations — Supabase Docs](https://supabase.com/docs/guides/deployment/database-migrations)
452
+ - [Database Branching — Supabase Docs](https://supabase.com/docs/guides/deployment/branching)
453
+ - [Supabase CLI Reference](https://supabase.com/docs/reference/cli/introduction)
454
+ - [createClient — @supabase/supabase-js](https://supabase.com/docs/reference/javascript/initializing)
455
+ - [GitHub Actions with Supabase](https://supabase.com/docs/guides/deployment/managing-environments#using-github-actions)
456
+ - [12-Factor App — Config](https://12factor.net/config)
220
457
 
221
458
  ## Next Steps
222
- For observability setup, see `supabase-observability`.
459
+
460
+ - For authentication patterns across environments, see `supabase-auth-storage-realtime-core`
461
+ - For RLS policy testing and validation, see `supabase-policy-guardrails`
462
+ - For local development workflow optimization, see `supabase-local-dev-loop`
463
+ - For monitoring and observability across environments, see `supabase-observability`
@@ -0,0 +1,59 @@
1
+ # Configuration Structure
2
+
3
+ ## Configuration Structure
4
+
5
+ ```
6
+ config/
7
+ ├── supabase/
8
+ │ ├── base.json # Shared config
9
+ │ ├── development.json # Dev overrides
10
+ │ ├── staging.json # Staging overrides
11
+ │ └── production.json # Prod overrides
12
+ ```
13
+
14
+ ### base.json
15
+
16
+ ```json
17
+ {
18
+ "timeout": 30000,
19
+ "retries": 3,
20
+ "cache": {
21
+ "enabled": true,
22
+ "ttlSeconds": 60
23
+ }
24
+ }
25
+ ```
26
+
27
+ ### development.json
28
+
29
+ ```json
30
+ {
31
+ "apiKey": "${SUPABASE_API_KEY}",
32
+ "baseUrl": "https://api-sandbox.supabase.com",
33
+ "debug": true,
34
+ "cache": {
35
+ "enabled": false
36
+ }
37
+ }
38
+ ```
39
+
40
+ ### staging.json
41
+
42
+ ```json
43
+ {
44
+ "apiKey": "${SUPABASE_API_KEY_STAGING}",
45
+ "baseUrl": "https://api-staging.supabase.com",
46
+ "debug": false
47
+ }
48
+ ```
49
+
50
+ ### production.json
51
+
52
+ ```json
53
+ {
54
+ "apiKey": "${SUPABASE_API_KEY_PROD}",
55
+ "baseUrl": "https://api.supabase.com",
56
+ "debug": false,
57
+ "retries": 5
58
+ }
59
+ ```