@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,73 +1,507 @@
1
1
  ---
2
2
  name: supabase-auth-storage-realtime-core
3
- description: |
4
- Execute Supabase secondary workflow: Auth + Storage + Realtime.
5
- Use when implementing secondary use case,
6
- or complementing primary workflow.
7
- Trigger with phrases like "supabase auth storage realtime",
8
- "implement full stack features with supabase".
9
- allowed-tools: Read, Write, Edit, Bash(npm:*), Grep
3
+ description: 'Implement Supabase Auth (signUp, signIn, OAuth, session management),
4
+ Storage
5
+
6
+ (upload, download, signed URLs, bucket policies), and Realtime (Postgres changes,
7
+
8
+ broadcast, presence). Use when building user auth flows, file upload features,
9
+
10
+ or live-updating UIs with Supabase. Trigger with phrases like "supabase auth",
11
+
12
+ "supabase storage upload", "supabase realtime subscribe", "supabase oauth",
13
+
14
+ "supabase file upload", "supabase presence", "supabase rls storage".
15
+
16
+ '
17
+ allowed-tools: Read, Write, Edit, Bash(npm:*), Bash(supabase:*), Grep
10
18
  version: 1.0.0
11
19
  license: MIT
12
20
  author: Jeremy Longshore <jeremy@intentsolutions.io>
21
+ tags:
22
+ - saas
23
+ - supabase
24
+ - auth
25
+ - storage
26
+ - realtime
27
+ - rls
28
+ compatibility: Designed for Claude Code, also compatible with Cursor
13
29
  ---
14
-
15
- # Supabase Auth + Storage + Realtime
30
+ # Supabase Auth + Storage + Realtime Core
16
31
 
17
32
  ## Overview
18
- Implement the core Supabase trifecta: authentication, file storage,
19
- and real-time subscriptions in a single cohesive setup.
20
33
 
34
+ Implement the three pillars that turn a Supabase database into a full application backend: user authentication (email/password, OAuth, magic links, session lifecycle), file storage (uploads, downloads, signed URLs, bucket-level RLS policies), and real-time subscriptions (Postgres change events, client-to-client broadcast, presence tracking). Every operation integrates with Row-Level Security through `auth.uid()`.
21
35
 
22
36
  ## Prerequisites
23
- - Completed `supabase-install-auth` setup
24
- - Familiarity with `supabase-schema-from-requirements`
25
- - Valid API credentials configured
37
+
38
+ - Supabase project created at [supabase.com/dashboard](https://supabase.com/dashboard)
39
+ - `@supabase/supabase-js` v2 installed (`npm install @supabase/supabase-js`)
40
+ - `SUPABASE_URL` and `SUPABASE_ANON_KEY` available from project Settings > API
41
+ - For Python: `pip install supabase` (wraps `postgrest-py`, `gotrue-py`, `storage3`, `realtime-py`)
26
42
 
27
43
  ## Instructions
28
44
 
29
- ### Step 1: Setup
45
+ ### Step 1: Auth — User Registration, Login, and OAuth
46
+
47
+ Initialize the client and implement the three primary auth flows: email/password, OAuth provider, and passwordless magic link.
48
+
49
+ **TypeScript**
50
+
51
+ ```typescript
52
+ import { createClient } from '@supabase/supabase-js'
53
+
54
+ const supabase = createClient(
55
+ process.env.SUPABASE_URL!,
56
+ process.env.SUPABASE_ANON_KEY!
57
+ )
58
+
59
+ // ── Sign up a new user ──
60
+ const { data: signUpData, error: signUpError } = await supabase.auth.signUp({
61
+ email: 'user@example.com',
62
+ password: 'secure-password-123',
63
+ options: {
64
+ data: { username: 'newuser', full_name: 'New User' }, // → raw_user_meta_data
65
+ },
66
+ })
67
+ // If email confirmation enabled: data.user exists but data.session is null
68
+ // If email confirmation disabled: both data.user and data.session are present
69
+
70
+ // ── Sign in with password ──
71
+ const { data: signInData, error: signInError } = await supabase.auth.signInWithPassword({
72
+ email: 'user@example.com',
73
+ password: 'secure-password-123',
74
+ })
75
+ const { user, session } = signInData
76
+ // session.access_token → JWT for authenticated API calls
77
+
78
+ // ── Sign in with OAuth (Google) ──
79
+ const { data: oauthData, error: oauthError } = await supabase.auth.signInWithOAuth({
80
+ provider: 'google',
81
+ options: {
82
+ redirectTo: 'https://myapp.com/auth/callback',
83
+ queryParams: { access_type: 'offline', prompt: 'consent' },
84
+ },
85
+ })
86
+ // Redirect user to oauthData.url in the browser
87
+
88
+ // ── Sign in with GitHub ──
89
+ const { data, error } = await supabase.auth.signInWithOAuth({
90
+ provider: 'github',
91
+ options: { redirectTo: 'https://myapp.com/auth/callback' },
92
+ })
93
+
94
+ // ── Passwordless magic link ──
95
+ const { error: otpError } = await supabase.auth.signInWithOtp({
96
+ email: 'user@example.com',
97
+ options: { emailRedirectTo: 'https://myapp.com/auth/callback' },
98
+ })
99
+
100
+ // ── Handle OAuth/magic link callback (in /auth/callback route) ──
101
+ const { data: { session: cbSession }, error: cbError } =
102
+ await supabase.auth.exchangeCodeForSession(code)
103
+ ```
104
+
105
+ **Session management — every app needs these:**
106
+
107
+ ```typescript
108
+ // Get current session (reads from local storage, no network call)
109
+ const { data: { session } } = await supabase.auth.getSession()
110
+
111
+ // Get current user (validates JWT against server)
112
+ const { data: { user } } = await supabase.auth.getUser()
113
+
114
+ // Listen for auth state changes — critical for reactive UIs
115
+ const { data: { subscription } } = supabase.auth.onAuthStateChange(
116
+ (event, session) => {
117
+ // event: 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'USER_UPDATED'
118
+ // 'INITIAL_SESSION' | 'PASSWORD_RECOVERY' | 'MFA_CHALLENGE_VERIFIED'
119
+ console.log('Auth event:', event, session?.user?.email)
120
+ }
121
+ )
122
+ // Clean up when component unmounts
123
+ subscription.unsubscribe()
124
+
125
+ // Sign out (clears session from storage)
126
+ await supabase.auth.signOut()
127
+
128
+ // Password reset (sends email with reset link)
129
+ await supabase.auth.resetPasswordForEmail('user@example.com', {
130
+ redirectTo: 'https://myapp.com/auth/reset-password',
131
+ })
132
+ ```
133
+
134
+ **Python**
135
+
136
+ ```python
137
+ from supabase import create_client
138
+
139
+ supabase = create_client(
140
+ "https://your-project.supabase.co",
141
+ "your-anon-key"
142
+ )
143
+
144
+ # Sign up
145
+ result = supabase.auth.sign_up({
146
+ "email": "user@example.com",
147
+ "password": "secure-password-123",
148
+ "options": {"data": {"username": "newuser"}},
149
+ })
150
+
151
+ # Sign in with password
152
+ result = supabase.auth.sign_in_with_password({
153
+ "email": "user@example.com",
154
+ "password": "secure-password-123",
155
+ })
156
+ access_token = result.session.access_token
157
+
158
+ # Get current session
159
+ session = supabase.auth.get_session()
160
+
161
+ # Sign out
162
+ supabase.auth.sign_out()
163
+ ```
164
+
165
+ ### Step 2: Storage — Upload, Download, and Secure with Bucket Policies
166
+
167
+ Supabase Storage organizes files into buckets. Public buckets serve files via CDN URLs; private buckets require signed URLs or authenticated requests.
168
+
169
+ **TypeScript**
170
+
171
+ ```typescript
172
+ // ── Upload a file ──
173
+ const file = new File(['hello world'], 'hello.txt', { type: 'text/plain' })
174
+ const { data, error } = await supabase.storage
175
+ .from('avatars') // bucket name
176
+ .upload('user123/avatar.png', file, {
177
+ cacheControl: '3600',
178
+ upsert: false, // true → overwrite existing
179
+ contentType: 'image/png',
180
+ })
181
+ // data.path → 'user123/avatar.png'
182
+
183
+ // ── Download a file ──
184
+ const { data: blob, error: dlError } = await supabase.storage
185
+ .from('avatars')
186
+ .download('user123/avatar.png')
187
+ // blob is a Blob object — use URL.createObjectURL(blob) for display
188
+
189
+ // ── Get public URL (public buckets only, no auth required) ──
190
+ const { data: { publicUrl } } = supabase.storage
191
+ .from('avatars')
192
+ .getPublicUrl('user123/avatar.png')
193
+ // publicUrl → 'https://<project>.supabase.co/storage/v1/object/public/avatars/user123/avatar.png'
194
+
195
+ // ── Create signed URL (private buckets, time-limited access) ──
196
+ const { data: signedUrlData, error: signError } = await supabase.storage
197
+ .from('documents')
198
+ .createSignedUrl('reports/q4-2025.pdf', 3600) // expires in 1 hour
199
+ // signedUrlData.signedUrl → one-time use URL with token parameter
200
+
201
+ // ── List files in a path ──
202
+ const { data: files, error: listError } = await supabase.storage
203
+ .from('documents')
204
+ .list('reports', {
205
+ limit: 100,
206
+ offset: 0,
207
+ sortBy: { column: 'name', order: 'asc' },
208
+ })
209
+
210
+ // ── Delete files ──
211
+ const { error: removeError } = await supabase.storage
212
+ .from('documents')
213
+ .remove(['reports/old-report.pdf', 'reports/draft.docx'])
214
+ ```
215
+
216
+ **Bucket RLS policies — enforce access control in SQL migrations:**
217
+
218
+ ```sql
219
+ -- Create buckets (run in a migration or SQL editor)
220
+ INSERT INTO storage.buckets (id, name, public)
221
+ VALUES ('avatars', 'avatars', true); -- public: anyone can read
222
+
223
+ INSERT INTO storage.buckets (id, name, public)
224
+ VALUES ('documents', 'documents', false); -- private: signed URLs only
225
+
226
+ -- Allow authenticated users to upload to their own folder
227
+ -- Convention: store files at <user_id>/filename.ext
228
+ CREATE POLICY "avatar_upload"
229
+ ON storage.objects FOR INSERT
230
+ WITH CHECK (
231
+ bucket_id = 'avatars'
232
+ AND auth.uid()::text = (storage.foldername(name))[1]
233
+ );
234
+
235
+ -- Allow anyone to view avatars (public bucket)
236
+ CREATE POLICY "avatar_public_read"
237
+ ON storage.objects FOR SELECT
238
+ USING (bucket_id = 'avatars');
239
+
240
+ -- Allow users to manage only their own documents (all operations)
241
+ CREATE POLICY "documents_user_crud"
242
+ ON storage.objects FOR ALL
243
+ USING (
244
+ bucket_id = 'documents'
245
+ AND auth.uid()::text = (storage.foldername(name))[1]
246
+ )
247
+ WITH CHECK (
248
+ bucket_id = 'documents'
249
+ AND auth.uid()::text = (storage.foldername(name))[1]
250
+ );
251
+
252
+ -- Allow users to delete only files they uploaded
253
+ CREATE POLICY "documents_owner_delete"
254
+ ON storage.objects FOR DELETE
255
+ USING (
256
+ bucket_id = 'documents'
257
+ AND auth.uid() = owner
258
+ );
259
+ ```
260
+
261
+ **Python**
262
+
263
+ ```python
264
+ # Upload
265
+ with open("report.pdf", "rb") as f:
266
+ result = supabase.storage.from_("documents").upload(
267
+ "user123/report.pdf", f,
268
+ {"content-type": "application/pdf", "cache-control": "3600"}
269
+ )
270
+
271
+ # Download
272
+ data = supabase.storage.from_("documents").download("user123/report.pdf")
273
+
274
+ # Public URL
275
+ url = supabase.storage.from_("avatars").get_public_url("user123/avatar.png")
276
+
277
+ # Signed URL (3600 seconds)
278
+ result = supabase.storage.from_("documents").create_signed_url(
279
+ "user123/report.pdf", 3600
280
+ )
281
+ signed_url = result["signedURL"]
282
+
283
+ # List files
284
+ files = supabase.storage.from_("documents").list("user123")
285
+
286
+ # Delete
287
+ supabase.storage.from_("documents").remove(["user123/old-file.pdf"])
288
+ ```
289
+
290
+ ### Step 3: Realtime — Postgres Changes, Broadcast, and Presence
291
+
292
+ Supabase Realtime provides three channel types: database change listeners, client-to-client broadcast, and presence tracking for online status.
293
+
294
+ **Postgres Changes (listen to INSERT/UPDATE/DELETE on tables):**
295
+
30
296
  ```typescript
31
- // Step 1 implementation
297
+ // Subscribe to new messages in a chat table
298
+ const channel = supabase
299
+ .channel('chat-room')
300
+ .on(
301
+ 'postgres_changes',
302
+ {
303
+ event: 'INSERT',
304
+ schema: 'public',
305
+ table: 'messages',
306
+ },
307
+ (payload) => {
308
+ console.log('New message:', payload.new)
309
+ // payload.new → full row data
310
+ // payload.old → null for INSERT
311
+ }
312
+ )
313
+ .on(
314
+ 'postgres_changes',
315
+ {
316
+ event: 'UPDATE',
317
+ schema: 'public',
318
+ table: 'messages',
319
+ filter: 'room_id=eq.42', // server-side filter
320
+ },
321
+ (payload) => {
322
+ console.log('Updated:', payload.old, '→', payload.new)
323
+ }
324
+ )
325
+ .on(
326
+ 'postgres_changes',
327
+ {
328
+ event: 'DELETE',
329
+ schema: 'public',
330
+ table: 'messages',
331
+ },
332
+ (payload) => {
333
+ console.log('Deleted:', payload.old)
334
+ // payload.new → null for DELETE
335
+ }
336
+ )
337
+ .subscribe((status) => {
338
+ console.log('Channel status:', status)
339
+ // 'SUBSCRIBED' | 'TIMED_OUT' | 'CLOSED' | 'CHANNEL_ERROR'
340
+ })
341
+
342
+ // Enable Realtime on the table (required one-time setup in SQL)
343
+ // ALTER PUBLICATION supabase_realtime ADD TABLE messages;
344
+
345
+ // Unsubscribe when done
346
+ supabase.removeChannel(channel)
347
+ ```
348
+
349
+ **RLS integration — Realtime respects row-level security:**
350
+
351
+ ```sql
352
+ -- Only receive changes for rows the user owns
353
+ CREATE POLICY "users_own_messages"
354
+ ON messages FOR SELECT
355
+ USING (auth.uid() = user_id);
356
+
357
+ -- The Realtime listener will only fire for rows passing this policy
32
358
  ```
33
359
 
34
- ### Step 2: Process
360
+ **Broadcast (client-to-client, no database involved):**
361
+
35
362
  ```typescript
36
- // Step 2 implementation
363
+ const room = supabase.channel('collab-room')
364
+
365
+ // Listen for cursor movements from other users
366
+ room.on('broadcast', { event: 'cursor-move' }, ({ payload }) => {
367
+ console.log(`User ${payload.userId} at (${payload.x}, ${payload.y})`)
368
+ })
369
+
370
+ // Subscribe first, then send
371
+ room.subscribe((status) => {
372
+ if (status === 'SUBSCRIBED') {
373
+ // Send cursor position to all other clients
374
+ room.send({
375
+ type: 'broadcast',
376
+ event: 'cursor-move',
377
+ payload: { userId: 'abc', x: 120, y: 340 },
378
+ })
379
+ }
380
+ })
37
381
  ```
38
382
 
39
- ### Step 3: Complete
383
+ **Presence (track who is online):**
384
+
40
385
  ```typescript
41
- // Step 3 implementation
386
+ const room = supabase.channel('app-presence')
387
+
388
+ // Sync event fires whenever the presence state changes
389
+ room.on('presence', { event: 'sync' }, () => {
390
+ const state = room.presenceState()
391
+ // state → { 'user-abc': [{ user_id: 'abc', online_at: '...' }], ... }
392
+ const onlineUsers = Object.keys(state)
393
+ console.log('Online:', onlineUsers.length, 'users')
394
+ })
395
+
396
+ room.on('presence', { event: 'join' }, ({ key, newPresences }) => {
397
+ console.log('Joined:', key, newPresences)
398
+ })
399
+
400
+ room.on('presence', { event: 'leave' }, ({ key, leftPresences }) => {
401
+ console.log('Left:', key, leftPresences)
402
+ })
403
+
404
+ // Subscribe and track this user's presence
405
+ room.subscribe(async (status) => {
406
+ if (status === 'SUBSCRIBED') {
407
+ await room.track({
408
+ user_id: currentUser.id,
409
+ username: currentUser.email,
410
+ online_at: new Date().toISOString(),
411
+ })
412
+ }
413
+ })
414
+
415
+ // Untrack when leaving (e.g., on component unmount)
416
+ await room.untrack()
417
+ ```
418
+
419
+ **Python Realtime:**
420
+
421
+ ```python
422
+ # Python realtime uses callbacks (requires running event loop)
423
+ def handle_insert(payload):
424
+ print("New row:", payload["new"])
425
+
426
+ channel = supabase.channel("room")
427
+ channel.on_postgres_changes(
428
+ event="INSERT",
429
+ schema="public",
430
+ table="messages",
431
+ callback=handle_insert,
432
+ )
433
+ channel.subscribe()
434
+
435
+ # When done
436
+ supabase.remove_channel(channel)
42
437
  ```
43
438
 
44
439
  ## Output
45
- - Completed Auth + Storage + Realtime execution
46
- - Results from Supabase API
47
- - Success confirmation or error details
440
+
441
+ - Auth: user registration, password login, OAuth flow (Google/GitHub), magic link, session lifecycle with `onAuthStateChange`, password reset
442
+ - Storage: file upload/download, public URLs for CDN-served assets, time-limited signed URLs for private files, bucket-level RLS policies using `auth.uid()` and `storage.foldername()`
443
+ - Realtime: Postgres change subscriptions with server-side filters, broadcast channels for client-to-client messaging, presence tracking for online status
48
444
 
49
445
  ## Error Handling
50
- | Aspect | Schema from Requirements | Auth + Storage + Realtime |
51
- |--------|------------|------------|
52
- | Use Case | Starting a new project with defined data requirements | Secondary |
53
- | Complexity | Medium | Lower |
54
- | Performance | Standard | Optimized |
446
+
447
+ | Error | Cause | Solution |
448
+ |-------|-------|----------|
449
+ | `AuthApiError: User already registered` | Duplicate email signup | Use `signInWithPassword` or check existence first |
450
+ | `AuthApiError: Invalid login credentials` | Wrong email or password | Verify credentials; check email confirmation status |
451
+ | `AuthApiError: Email not confirmed` | User has not clicked confirmation link | Resend with `resend({ type: 'signup', email })` |
452
+ | `StorageApiError: Bucket not found` | Bucket does not exist | Create via dashboard or `INSERT INTO storage.buckets` |
453
+ | `StorageApiError: new row violates row-level security` | RLS policy blocking the operation | Verify `storage.objects` policies match the user and bucket |
454
+ | `StorageApiError: The resource already exists` | File exists and `upsert: false` | Set `upsert: true` to overwrite or use a unique path |
455
+ | `Realtime: channel error` or `TIMED_OUT` | Network issues or Realtime not enabled | Check `ALTER PUBLICATION supabase_realtime ADD TABLE <name>` |
456
+ | `Realtime: too many channels` | Exceeded concurrent channel limit | Unsubscribe unused channels with `removeChannel()` |
55
457
 
56
458
  ## Examples
57
459
 
58
- ### Complete Workflow
59
- ```typescript
60
- // Complete workflow example
61
- ```
460
+ **Full auth + protected upload flow:**
62
461
 
63
- ### Error Recovery
64
462
  ```typescript
65
- // Error handling code
463
+ // 1. Sign in
464
+ const { data: { session } } = await supabase.auth.signInWithPassword({
465
+ email: 'user@example.com',
466
+ password: 'secure-password-123',
467
+ })
468
+
469
+ // 2. Upload avatar to user's folder (RLS enforces ownership)
470
+ const { data } = await supabase.storage
471
+ .from('avatars')
472
+ .upload(`${session.user.id}/avatar.png`, file, { upsert: true })
473
+
474
+ // 3. Get public URL for display
475
+ const { data: { publicUrl } } = supabase.storage
476
+ .from('avatars')
477
+ .getPublicUrl(`${session.user.id}/avatar.png`)
478
+
479
+ // 4. Subscribe to profile changes in real time
480
+ const channel = supabase
481
+ .channel('profile-updates')
482
+ .on('postgres_changes', {
483
+ event: 'UPDATE',
484
+ schema: 'public',
485
+ table: 'profiles',
486
+ filter: `id=eq.${session.user.id}`,
487
+ }, (payload) => {
488
+ console.log('Profile updated:', payload.new)
489
+ })
490
+ .subscribe()
66
491
  ```
67
492
 
68
493
  ## Resources
69
- - [Supabase Documentation](https://supabase.com/docs)
70
- - [Supabase API Reference](https://supabase.com/docs/api)
494
+
495
+ - [Auth Guide](https://supabase.com/docs/guides/auth)
496
+ - [Auth API Reference](https://supabase.com/docs/reference/javascript/auth-signup)
497
+ - [Storage Guide](https://supabase.com/docs/guides/storage)
498
+ - [Storage Access Control](https://supabase.com/docs/guides/storage/security/access-control)
499
+ - [Realtime Guide](https://supabase.com/docs/guides/realtime)
500
+ - [Realtime Postgres Changes](https://supabase.com/docs/guides/realtime/postgres-changes)
501
+ - [Realtime Broadcast](https://supabase.com/docs/guides/realtime/broadcast)
502
+ - [Realtime Presence](https://supabase.com/docs/guides/realtime/presence)
71
503
 
72
504
  ## Next Steps
73
- For common errors, see `supabase-common-errors`.
505
+
506
+ For common Supabase errors and debugging, see `supabase-common-errors`.
507
+ For database queries and CRUD operations, see `supabase-crud-core`.