@intentsolutionsio/supabase-pack 1.0.0
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.
- package/.claude-plugin/plugin.json +17 -0
- package/000-docs/001-BL-LICN-license.txt +3 -0
- package/LICENSE +21 -0
- package/README.md +69 -0
- package/package.json +43 -0
- package/skills/supabase-advanced-troubleshooting/SKILL.md +261 -0
- package/skills/supabase-architecture-variants/SKILL.md +284 -0
- package/skills/supabase-auth-storage-realtime-core/SKILL.md +73 -0
- package/skills/supabase-ci-integration/SKILL.md +124 -0
- package/skills/supabase-common-errors/SKILL.md +109 -0
- package/skills/supabase-cost-tuning/SKILL.md +201 -0
- package/skills/supabase-data-handling/SKILL.md +220 -0
- package/skills/supabase-debug-bundle/SKILL.md +111 -0
- package/skills/supabase-deploy-integration/SKILL.md +209 -0
- package/skills/supabase-enterprise-rbac/SKILL.md +222 -0
- package/skills/supabase-hello-world/SKILL.md +96 -0
- package/skills/supabase-incident-runbook/SKILL.md +203 -0
- package/skills/supabase-install-auth/SKILL.md +90 -0
- package/skills/supabase-known-pitfalls/SKILL.md +334 -0
- package/skills/supabase-load-scale/SKILL.md +274 -0
- package/skills/supabase-local-dev-loop/SKILL.md +117 -0
- package/skills/supabase-migration-deep-dive/SKILL.md +244 -0
- package/skills/supabase-multi-env-setup/SKILL.md +222 -0
- package/skills/supabase-observability/SKILL.md +250 -0
- package/skills/supabase-performance-tuning/SKILL.md +214 -0
- package/skills/supabase-policy-guardrails/SKILL.md +257 -0
- package/skills/supabase-prod-checklist/SKILL.md +119 -0
- package/skills/supabase-rate-limits/SKILL.md +149 -0
- package/skills/supabase-reference-architecture/SKILL.md +238 -0
- package/skills/supabase-reliability-patterns/SKILL.md +290 -0
- package/skills/supabase-schema-from-requirements/SKILL.md +71 -0
- package/skills/supabase-sdk-patterns/SKILL.md +147 -0
- package/skills/supabase-security-basics/SKILL.md +140 -0
- package/skills/supabase-upgrade-migration/SKILL.md +112 -0
- package/skills/supabase-webhooks-events/SKILL.md +199 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "supabase-pack",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Claude Code skill pack for Supabase (30 skills)",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Jeremy Longshore",
|
|
7
|
+
"email": "jeremy@intentsolutions.io"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"supabase",
|
|
12
|
+
"supabase",
|
|
13
|
+
"saas",
|
|
14
|
+
"sdk",
|
|
15
|
+
"integration"
|
|
16
|
+
]
|
|
17
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Jeremy Longshore
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Supabase Skill Pack
|
|
2
|
+
|
|
3
|
+
> Claude Code skill pack for Supabase integration (30 skills)
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
/plugin install supabase-pack@claude-code-plugins-plus
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Skills Included
|
|
12
|
+
|
|
13
|
+
### Standard Skills (S01-S12)
|
|
14
|
+
| Skill | Description |
|
|
15
|
+
|-------|-------------|
|
|
16
|
+
| `supabase-install-auth` | Install Auth |
|
|
17
|
+
| `supabase-hello-world` | Hello World |
|
|
18
|
+
| `supabase-local-dev-loop` | Local Dev Loop |
|
|
19
|
+
| `supabase-sdk-patterns` | Sdk Patterns |
|
|
20
|
+
| `supabase-schema-from-requirements` | Schema From Requirements |
|
|
21
|
+
| `supabase-auth-storage-realtime-core` | Auth Storage Realtime Core |
|
|
22
|
+
| `supabase-common-errors` | Common Errors |
|
|
23
|
+
| `supabase-debug-bundle` | Debug Bundle |
|
|
24
|
+
| `supabase-rate-limits` | Rate Limits |
|
|
25
|
+
| `supabase-security-basics` | Security Basics |
|
|
26
|
+
| `supabase-prod-checklist` | Prod Checklist |
|
|
27
|
+
| `supabase-upgrade-migration` | Upgrade Migration |
|
|
28
|
+
|
|
29
|
+
### Pro Skills (P13-P18)
|
|
30
|
+
| Skill | Description |
|
|
31
|
+
|-------|-------------|
|
|
32
|
+
| `supabase-ci-integration` | Ci Integration |
|
|
33
|
+
| `supabase-deploy-integration` | Deploy Integration |
|
|
34
|
+
| `supabase-webhooks-events` | Webhooks Events |
|
|
35
|
+
| `supabase-performance-tuning` | Performance Tuning |
|
|
36
|
+
| `supabase-cost-tuning` | Cost Tuning |
|
|
37
|
+
| `supabase-reference-architecture` | Reference Architecture |
|
|
38
|
+
|
|
39
|
+
### Flagship Skills (F19-F24)
|
|
40
|
+
| Skill | Description |
|
|
41
|
+
|-------|-------------|
|
|
42
|
+
| `supabase-multi-env-setup` | Multi Env Setup |
|
|
43
|
+
| `supabase-observability` | Observability |
|
|
44
|
+
| `supabase-incident-runbook` | Incident Runbook |
|
|
45
|
+
| `supabase-data-handling` | Data Handling |
|
|
46
|
+
| `supabase-enterprise-rbac` | Enterprise Rbac |
|
|
47
|
+
| `supabase-migration-deep-dive` | Migration Deep Dive |
|
|
48
|
+
|
|
49
|
+
### Flagship+ Skills (X25-X30)
|
|
50
|
+
| Skill | Description |
|
|
51
|
+
|-------|-------------|
|
|
52
|
+
| `supabase-advanced-troubleshooting` | Advanced Troubleshooting |
|
|
53
|
+
| `supabase-load-scale` | Load Scale |
|
|
54
|
+
| `supabase-reliability-patterns` | Reliability Patterns |
|
|
55
|
+
| `supabase-policy-guardrails` | Policy Guardrails |
|
|
56
|
+
| `supabase-architecture-variants` | Architecture Variants |
|
|
57
|
+
| `supabase-known-pitfalls` | Known Pitfalls |
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
Skills trigger automatically when you discuss Supabase topics. For example:
|
|
62
|
+
|
|
63
|
+
- "Help me set up Supabase" → triggers `supabase-install-auth`
|
|
64
|
+
- "Debug this Supabase error" → triggers `supabase-common-errors`
|
|
65
|
+
- "Deploy my Supabase integration" → triggers `supabase-deploy-integration`
|
|
66
|
+
|
|
67
|
+
## License
|
|
68
|
+
|
|
69
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@intentsolutionsio/supabase-pack",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Claude Code skill pack for Supabase - 30 skills covering database operations, authentication, edge functions, realtime subscriptions, and production operations",
|
|
5
|
+
"main": "README.md",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"files": [
|
|
8
|
+
"README.md",
|
|
9
|
+
"LICENSE",
|
|
10
|
+
".claude-plugin/",
|
|
11
|
+
"skills/",
|
|
12
|
+
"000-docs/"
|
|
13
|
+
],
|
|
14
|
+
"keywords": [
|
|
15
|
+
"claude-code",
|
|
16
|
+
"claude-code-plugin",
|
|
17
|
+
"supabase",
|
|
18
|
+
"database",
|
|
19
|
+
"postgres",
|
|
20
|
+
"authentication",
|
|
21
|
+
"edge-functions",
|
|
22
|
+
"realtime",
|
|
23
|
+
"ai-skills",
|
|
24
|
+
"saas-pack"
|
|
25
|
+
],
|
|
26
|
+
"author": {
|
|
27
|
+
"name": "Jeremy Longshore",
|
|
28
|
+
"email": "jeremy@intentsolutions.io"
|
|
29
|
+
},
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/jeremylongshore/claude-code-plugins.git",
|
|
34
|
+
"directory": "plugins/saas-packs/supabase-pack"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/jeremylongshore/claude-code-plugins/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://claudecodeplugins.io/plugins/supabase-pack",
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: supabase-advanced-troubleshooting
|
|
3
|
+
description: |
|
|
4
|
+
Apply Supabase advanced debugging techniques for hard-to-diagnose issues.
|
|
5
|
+
Use when standard troubleshooting fails, investigating complex race conditions,
|
|
6
|
+
or preparing evidence bundles for Supabase support escalation.
|
|
7
|
+
Trigger with phrases like "supabase hard bug", "supabase mystery error",
|
|
8
|
+
"supabase impossible to debug", "difficult supabase issue", "supabase deep debug".
|
|
9
|
+
allowed-tools: Read, Grep, Bash(kubectl:*), Bash(curl:*), Bash(tcpdump:*)
|
|
10
|
+
version: 1.0.0
|
|
11
|
+
license: MIT
|
|
12
|
+
author: Jeremy Longshore <jeremy@intentsolutions.io>
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Supabase Advanced Troubleshooting
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
Deep debugging techniques for complex Supabase issues that resist standard troubleshooting.
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
- Access to production logs and metrics
|
|
22
|
+
- kubectl access to clusters
|
|
23
|
+
- Network capture tools available
|
|
24
|
+
- Understanding of distributed tracing
|
|
25
|
+
|
|
26
|
+
## Evidence Collection Framework
|
|
27
|
+
|
|
28
|
+
### Comprehensive Debug Bundle
|
|
29
|
+
```bash
|
|
30
|
+
#!/bin/bash
|
|
31
|
+
# advanced-supabase-debug.sh
|
|
32
|
+
|
|
33
|
+
BUNDLE="supabase-advanced-debug-$(date +%Y%m%d-%H%M%S)"
|
|
34
|
+
mkdir -p "$BUNDLE"/{logs,metrics,network,config,traces}
|
|
35
|
+
|
|
36
|
+
# 1. Extended logs (1 hour window)
|
|
37
|
+
kubectl logs -l app=supabase-integration --since=1h > "$BUNDLE/logs/pods.log"
|
|
38
|
+
journalctl -u supabase-service --since "1 hour ago" > "$BUNDLE/logs/system.log"
|
|
39
|
+
|
|
40
|
+
# 2. Metrics dump
|
|
41
|
+
curl -s localhost:9090/api/v1/query?query=supabase_requests_total > "$BUNDLE/metrics/requests.json"
|
|
42
|
+
curl -s localhost:9090/api/v1/query?query=supabase_errors_total > "$BUNDLE/metrics/errors.json"
|
|
43
|
+
|
|
44
|
+
# 3. Network capture (30 seconds)
|
|
45
|
+
timeout 30 tcpdump -i any port 443 -w "$BUNDLE/network/capture.pcap" &
|
|
46
|
+
|
|
47
|
+
# 4. Distributed traces
|
|
48
|
+
curl -s localhost:16686/api/traces?service=supabase > "$BUNDLE/traces/jaeger.json"
|
|
49
|
+
|
|
50
|
+
# 5. Configuration state
|
|
51
|
+
kubectl get cm supabase-config -o yaml > "$BUNDLE/config/configmap.yaml"
|
|
52
|
+
kubectl get secret supabase-secrets -o yaml > "$BUNDLE/config/secrets-redacted.yaml"
|
|
53
|
+
|
|
54
|
+
tar -czf "$BUNDLE.tar.gz" "$BUNDLE"
|
|
55
|
+
echo "Advanced debug bundle: $BUNDLE.tar.gz"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Systematic Isolation
|
|
59
|
+
|
|
60
|
+
### Layer-by-Layer Testing
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// Test each layer independently
|
|
64
|
+
async function diagnoseSupabaseIssue(): Promise<DiagnosisReport> {
|
|
65
|
+
const results: DiagnosisResult[] = [];
|
|
66
|
+
|
|
67
|
+
// Layer 1: Network connectivity
|
|
68
|
+
results.push(await testNetworkConnectivity());
|
|
69
|
+
|
|
70
|
+
// Layer 2: DNS resolution
|
|
71
|
+
results.push(await testDNSResolution('api.supabase.com'));
|
|
72
|
+
|
|
73
|
+
// Layer 3: TLS handshake
|
|
74
|
+
results.push(await testTLSHandshake('api.supabase.com'));
|
|
75
|
+
|
|
76
|
+
// Layer 4: Authentication
|
|
77
|
+
results.push(await testAuthentication());
|
|
78
|
+
|
|
79
|
+
// Layer 5: API response
|
|
80
|
+
results.push(await testAPIResponse());
|
|
81
|
+
|
|
82
|
+
// Layer 6: Response parsing
|
|
83
|
+
results.push(await testResponseParsing());
|
|
84
|
+
|
|
85
|
+
return { results, firstFailure: results.find(r => !r.success) };
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Minimal Reproduction
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// Strip down to absolute minimum
|
|
93
|
+
async function minimalRepro(): Promise<void> {
|
|
94
|
+
// 1. Fresh client, no customization
|
|
95
|
+
const client = new SupabaseClient({
|
|
96
|
+
apiKey: process.env.SUPABASE_API_KEY!,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// 2. Simplest possible call
|
|
100
|
+
try {
|
|
101
|
+
const result = await client.ping();
|
|
102
|
+
console.log('Ping successful:', result);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('Ping failed:', {
|
|
105
|
+
message: error.message,
|
|
106
|
+
code: error.code,
|
|
107
|
+
stack: error.stack,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Timing Analysis
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
class TimingAnalyzer {
|
|
117
|
+
private timings: Map<string, number[]> = new Map();
|
|
118
|
+
|
|
119
|
+
async measure<T>(label: string, fn: () => Promise<T>): Promise<T> {
|
|
120
|
+
const start = performance.now();
|
|
121
|
+
try {
|
|
122
|
+
return await fn();
|
|
123
|
+
} finally {
|
|
124
|
+
const duration = performance.now() - start;
|
|
125
|
+
const existing = this.timings.get(label) || [];
|
|
126
|
+
existing.push(duration);
|
|
127
|
+
this.timings.set(label, existing);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
report(): TimingReport {
|
|
132
|
+
const report: TimingReport = {};
|
|
133
|
+
for (const [label, times] of this.timings) {
|
|
134
|
+
report[label] = {
|
|
135
|
+
count: times.length,
|
|
136
|
+
min: Math.min(...times),
|
|
137
|
+
max: Math.max(...times),
|
|
138
|
+
avg: times.reduce((a, b) => a + b, 0) / times.length,
|
|
139
|
+
p95: this.percentile(times, 95),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return report;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Memory and Resource Analysis
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// Detect memory leaks in Supabase client usage
|
|
151
|
+
const heapUsed: number[] = [];
|
|
152
|
+
|
|
153
|
+
setInterval(() => {
|
|
154
|
+
const usage = process.memoryUsage();
|
|
155
|
+
heapUsed.push(usage.heapUsed);
|
|
156
|
+
|
|
157
|
+
// Alert on sustained growth
|
|
158
|
+
if (heapUsed.length > 60) { // 1 hour at 1/min
|
|
159
|
+
const trend = heapUsed[59] - heapUsed[0];
|
|
160
|
+
if (trend > 100 * 1024 * 1024) { // 100MB growth
|
|
161
|
+
console.warn('Potential memory leak in supabase integration');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}, 60000);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Race Condition Detection
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
// Detect concurrent access issues
|
|
171
|
+
class SupabaseConcurrencyChecker {
|
|
172
|
+
private inProgress: Set<string> = new Set();
|
|
173
|
+
|
|
174
|
+
async execute<T>(key: string, fn: () => Promise<T>): Promise<T> {
|
|
175
|
+
if (this.inProgress.has(key)) {
|
|
176
|
+
console.warn(`Concurrent access detected for ${key}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.inProgress.add(key);
|
|
180
|
+
try {
|
|
181
|
+
return await fn();
|
|
182
|
+
} finally {
|
|
183
|
+
this.inProgress.delete(key);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Support Escalation Template
|
|
190
|
+
|
|
191
|
+
```markdown
|
|
192
|
+
## Supabase Support Escalation
|
|
193
|
+
|
|
194
|
+
**Severity:** P[1-4]
|
|
195
|
+
**Request ID:** [from error response]
|
|
196
|
+
**Timestamp:** [ISO 8601]
|
|
197
|
+
|
|
198
|
+
### Issue Summary
|
|
199
|
+
[One paragraph description]
|
|
200
|
+
|
|
201
|
+
### Steps to Reproduce
|
|
202
|
+
1. [Step 1]
|
|
203
|
+
2. [Step 2]
|
|
204
|
+
|
|
205
|
+
### Expected vs Actual
|
|
206
|
+
- Expected: [behavior]
|
|
207
|
+
- Actual: [behavior]
|
|
208
|
+
|
|
209
|
+
### Evidence Attached
|
|
210
|
+
- [ ] Debug bundle (supabase-advanced-debug-*.tar.gz)
|
|
211
|
+
- [ ] Minimal reproduction code
|
|
212
|
+
- [ ] Timing analysis
|
|
213
|
+
- [ ] Network capture (if relevant)
|
|
214
|
+
|
|
215
|
+
### Workarounds Attempted
|
|
216
|
+
1. [Workaround 1] - Result: [outcome]
|
|
217
|
+
2. [Workaround 2] - Result: [outcome]
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Instructions
|
|
221
|
+
|
|
222
|
+
### Step 1: Collect Evidence Bundle
|
|
223
|
+
Run the comprehensive debug script to gather all relevant data.
|
|
224
|
+
|
|
225
|
+
### Step 2: Systematic Isolation
|
|
226
|
+
Test each layer independently to identify the failure point.
|
|
227
|
+
|
|
228
|
+
### Step 3: Create Minimal Reproduction
|
|
229
|
+
Strip down to the simplest failing case.
|
|
230
|
+
|
|
231
|
+
### Step 4: Escalate with Evidence
|
|
232
|
+
Use the support template with all collected evidence.
|
|
233
|
+
|
|
234
|
+
## Output
|
|
235
|
+
- Comprehensive debug bundle collected
|
|
236
|
+
- Failure layer identified
|
|
237
|
+
- Minimal reproduction created
|
|
238
|
+
- Support escalation submitted
|
|
239
|
+
|
|
240
|
+
## Error Handling
|
|
241
|
+
| Issue | Cause | Solution |
|
|
242
|
+
|-------|-------|----------|
|
|
243
|
+
| Can't reproduce | Race condition | Add timing analysis |
|
|
244
|
+
| Intermittent failure | Timing-dependent | Increase sample size |
|
|
245
|
+
| No useful logs | Missing instrumentation | Add debug logging |
|
|
246
|
+
| Memory growth | Resource leak | Use heap profiling |
|
|
247
|
+
|
|
248
|
+
## Examples
|
|
249
|
+
|
|
250
|
+
### Quick Layer Test
|
|
251
|
+
```bash
|
|
252
|
+
# Test each layer in sequence
|
|
253
|
+
curl -v https://api.supabase.com/health 2>&1 | grep -E "(Connected|TLS|HTTP)"
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Resources
|
|
257
|
+
- [Supabase Support Portal](https://support.supabase.com)
|
|
258
|
+
- [Supabase Status Page](https://status.supabase.com)
|
|
259
|
+
|
|
260
|
+
## Next Steps
|
|
261
|
+
For load testing, see `supabase-load-scale`.
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: supabase-architecture-variants
|
|
3
|
+
description: |
|
|
4
|
+
Choose and implement Supabase validated architecture blueprints for different scales.
|
|
5
|
+
Use when designing new Supabase integrations, choosing between monolith/service/microservice
|
|
6
|
+
architectures, or planning migration paths for Supabase applications.
|
|
7
|
+
Trigger with phrases like "supabase architecture", "supabase blueprint",
|
|
8
|
+
"how to structure supabase", "supabase project layout", "supabase microservice".
|
|
9
|
+
allowed-tools: Read, Grep
|
|
10
|
+
version: 1.0.0
|
|
11
|
+
license: MIT
|
|
12
|
+
author: Jeremy Longshore <jeremy@intentsolutions.io>
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Supabase Architecture Variants
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
Three validated architecture blueprints for Supabase integrations.
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
- Understanding of team size and DAU requirements
|
|
22
|
+
- Knowledge of deployment infrastructure
|
|
23
|
+
- Clear SLA requirements
|
|
24
|
+
- Growth projections available
|
|
25
|
+
|
|
26
|
+
## Variant A: Monolith (Simple)
|
|
27
|
+
|
|
28
|
+
**Best for:** MVPs, small teams, < 10K daily active users
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
my-app/
|
|
32
|
+
├── src/
|
|
33
|
+
│ ├── supabase/
|
|
34
|
+
│ │ ├── client.ts # Singleton client
|
|
35
|
+
│ │ ├── types.ts # Types
|
|
36
|
+
│ │ └── middleware.ts # Express middleware
|
|
37
|
+
│ ├── routes/
|
|
38
|
+
│ │ └── api/
|
|
39
|
+
│ │ └── supabase.ts # API routes
|
|
40
|
+
│ └── index.ts
|
|
41
|
+
├── tests/
|
|
42
|
+
│ └── supabase.test.ts
|
|
43
|
+
└── package.json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Key Characteristics
|
|
47
|
+
- Single deployment unit
|
|
48
|
+
- Synchronous Supabase calls in request path
|
|
49
|
+
- In-memory caching
|
|
50
|
+
- Simple error handling
|
|
51
|
+
|
|
52
|
+
### Code Pattern
|
|
53
|
+
```typescript
|
|
54
|
+
// Direct integration in route handler
|
|
55
|
+
app.post('/api/create', async (req, res) => {
|
|
56
|
+
try {
|
|
57
|
+
const result = await supabaseClient.create(req.body);
|
|
58
|
+
res.json(result);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
res.status(500).json({ error: error.message });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Variant B: Service Layer (Moderate)
|
|
68
|
+
|
|
69
|
+
**Best for:** Growing startups, 10K-100K DAU, multiple integrations
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
my-app/
|
|
73
|
+
├── src/
|
|
74
|
+
│ ├── services/
|
|
75
|
+
│ │ ├── supabase/
|
|
76
|
+
│ │ │ ├── client.ts # Client wrapper
|
|
77
|
+
│ │ │ ├── service.ts # Business logic
|
|
78
|
+
│ │ │ ├── repository.ts # Data access
|
|
79
|
+
│ │ │ └── types.ts
|
|
80
|
+
│ │ └── index.ts # Service exports
|
|
81
|
+
│ ├── controllers/
|
|
82
|
+
│ │ └── supabase.ts
|
|
83
|
+
│ ├── routes/
|
|
84
|
+
│ ├── middleware/
|
|
85
|
+
│ ├── queue/
|
|
86
|
+
│ │ └── supabase-processor.ts # Async processing
|
|
87
|
+
│ └── index.ts
|
|
88
|
+
├── config/
|
|
89
|
+
│ └── supabase/
|
|
90
|
+
└── package.json
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Key Characteristics
|
|
94
|
+
- Separation of concerns
|
|
95
|
+
- Background job processing
|
|
96
|
+
- Redis caching
|
|
97
|
+
- Circuit breaker pattern
|
|
98
|
+
- Structured error handling
|
|
99
|
+
|
|
100
|
+
### Code Pattern
|
|
101
|
+
```typescript
|
|
102
|
+
// Service layer abstraction
|
|
103
|
+
class SupabaseService {
|
|
104
|
+
constructor(
|
|
105
|
+
private client: SupabaseClient,
|
|
106
|
+
private cache: CacheService,
|
|
107
|
+
private queue: QueueService
|
|
108
|
+
) {}
|
|
109
|
+
|
|
110
|
+
async createResource(data: CreateInput): Promise<Resource> {
|
|
111
|
+
// Business logic before API call
|
|
112
|
+
const validated = this.validate(data);
|
|
113
|
+
|
|
114
|
+
// Check cache
|
|
115
|
+
const cached = await this.cache.get(cacheKey);
|
|
116
|
+
if (cached) return cached;
|
|
117
|
+
|
|
118
|
+
// API call with retry
|
|
119
|
+
const result = await this.withRetry(() =>
|
|
120
|
+
this.client.create(validated)
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// Cache result
|
|
124
|
+
await this.cache.set(cacheKey, result, 300);
|
|
125
|
+
|
|
126
|
+
// Async follow-up
|
|
127
|
+
await this.queue.enqueue('supabase.post-create', result);
|
|
128
|
+
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Variant C: Microservice (Complex)
|
|
137
|
+
|
|
138
|
+
**Best for:** Enterprise, 100K+ DAU, strict SLAs
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
supabase-service/ # Dedicated microservice
|
|
142
|
+
├── src/
|
|
143
|
+
│ ├── api/
|
|
144
|
+
│ │ ├── grpc/
|
|
145
|
+
│ │ │ └── supabase.proto
|
|
146
|
+
│ │ └── rest/
|
|
147
|
+
│ │ └── routes.ts
|
|
148
|
+
│ ├── domain/
|
|
149
|
+
│ │ ├── entities/
|
|
150
|
+
│ │ ├── events/
|
|
151
|
+
│ │ └── services/
|
|
152
|
+
│ ├── infrastructure/
|
|
153
|
+
│ │ ├── supabase/
|
|
154
|
+
│ │ │ ├── client.ts
|
|
155
|
+
│ │ │ ├── mapper.ts
|
|
156
|
+
│ │ │ └── circuit-breaker.ts
|
|
157
|
+
│ │ ├── cache/
|
|
158
|
+
│ │ ├── queue/
|
|
159
|
+
│ │ └── database/
|
|
160
|
+
│ └── index.ts
|
|
161
|
+
├── config/
|
|
162
|
+
├── k8s/
|
|
163
|
+
│ ├── deployment.yaml
|
|
164
|
+
│ ├── service.yaml
|
|
165
|
+
│ └── hpa.yaml
|
|
166
|
+
└── package.json
|
|
167
|
+
|
|
168
|
+
other-services/
|
|
169
|
+
├── order-service/ # Calls supabase-service
|
|
170
|
+
├── payment-service/
|
|
171
|
+
└── notification-service/
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Key Characteristics
|
|
175
|
+
- Dedicated Supabase microservice
|
|
176
|
+
- gRPC for internal communication
|
|
177
|
+
- Event-driven architecture
|
|
178
|
+
- Database per service
|
|
179
|
+
- Kubernetes autoscaling
|
|
180
|
+
- Distributed tracing
|
|
181
|
+
- Circuit breaker per service
|
|
182
|
+
|
|
183
|
+
### Code Pattern
|
|
184
|
+
```typescript
|
|
185
|
+
// Event-driven with domain isolation
|
|
186
|
+
class SupabaseAggregate {
|
|
187
|
+
private events: DomainEvent[] = [];
|
|
188
|
+
|
|
189
|
+
process(command: SupabaseCommand): void {
|
|
190
|
+
// Domain logic
|
|
191
|
+
const result = this.execute(command);
|
|
192
|
+
|
|
193
|
+
// Emit domain event
|
|
194
|
+
this.events.push(new SupabaseProcessedEvent(result));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
getUncommittedEvents(): DomainEvent[] {
|
|
198
|
+
return [...this.events];
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Event handler
|
|
203
|
+
@EventHandler(SupabaseProcessedEvent)
|
|
204
|
+
class SupabaseEventHandler {
|
|
205
|
+
async handle(event: SupabaseProcessedEvent): Promise<void> {
|
|
206
|
+
// Saga orchestration
|
|
207
|
+
await this.sagaOrchestrator.continue(event);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Decision Matrix
|
|
215
|
+
|
|
216
|
+
| Factor | Monolith | Service Layer | Microservice |
|
|
217
|
+
|--------|----------|---------------|--------------|
|
|
218
|
+
| Team Size | 1-5 | 5-20 | 20+ |
|
|
219
|
+
| DAU | < 10K | 10K-100K | 100K+ |
|
|
220
|
+
| Deployment Frequency | Weekly | Daily | Continuous |
|
|
221
|
+
| Failure Isolation | None | Partial | Full |
|
|
222
|
+
| Operational Complexity | Low | Medium | High |
|
|
223
|
+
| Time to Market | Fastest | Moderate | Slowest |
|
|
224
|
+
|
|
225
|
+
## Migration Path
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
Monolith → Service Layer:
|
|
229
|
+
1. Extract Supabase code to service/
|
|
230
|
+
2. Add caching layer
|
|
231
|
+
3. Add background processing
|
|
232
|
+
|
|
233
|
+
Service Layer → Microservice:
|
|
234
|
+
1. Create dedicated supabase-service repo
|
|
235
|
+
2. Define gRPC contract
|
|
236
|
+
3. Add event bus
|
|
237
|
+
4. Deploy to Kubernetes
|
|
238
|
+
5. Migrate traffic gradually
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Instructions
|
|
242
|
+
|
|
243
|
+
### Step 1: Assess Requirements
|
|
244
|
+
Use the decision matrix to identify appropriate variant.
|
|
245
|
+
|
|
246
|
+
### Step 2: Choose Architecture
|
|
247
|
+
Select Monolith, Service Layer, or Microservice based on needs.
|
|
248
|
+
|
|
249
|
+
### Step 3: Implement Structure
|
|
250
|
+
Set up project layout following the chosen blueprint.
|
|
251
|
+
|
|
252
|
+
### Step 4: Plan Migration Path
|
|
253
|
+
Document upgrade path for future scaling.
|
|
254
|
+
|
|
255
|
+
## Output
|
|
256
|
+
- Architecture variant selected
|
|
257
|
+
- Project structure implemented
|
|
258
|
+
- Migration path documented
|
|
259
|
+
- Appropriate patterns applied
|
|
260
|
+
|
|
261
|
+
## Error Handling
|
|
262
|
+
| Issue | Cause | Solution |
|
|
263
|
+
|-------|-------|----------|
|
|
264
|
+
| Over-engineering | Wrong variant choice | Start simpler |
|
|
265
|
+
| Performance issues | Wrong layer | Add caching/async |
|
|
266
|
+
| Team friction | Complex architecture | Simplify or train |
|
|
267
|
+
| Deployment complexity | Microservice overhead | Consider service layer |
|
|
268
|
+
|
|
269
|
+
## Examples
|
|
270
|
+
|
|
271
|
+
### Quick Variant Check
|
|
272
|
+
```bash
|
|
273
|
+
# Count team size and DAU to select variant
|
|
274
|
+
echo "Team: $(git log --format='%ae' | sort -u | wc -l) developers"
|
|
275
|
+
echo "DAU: Check analytics dashboard"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Resources
|
|
279
|
+
- [Monolith First](https://martinfowler.com/bliki/MonolithFirst.html)
|
|
280
|
+
- [Microservices Guide](https://martinfowler.com/microservices/)
|
|
281
|
+
- [Supabase Architecture Guide](https://supabase.com/docs/architecture)
|
|
282
|
+
|
|
283
|
+
## Next Steps
|
|
284
|
+
For common anti-patterns, see `supabase-known-pitfalls`.
|