@odvi/create-dtt-framework 0.1.2 → 0.1.5

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 (114) hide show
  1. package/dist/commands/create.d.ts.map +1 -1
  2. package/dist/commands/create.js +16 -13
  3. package/dist/commands/create.js.map +1 -1
  4. package/dist/utils/template.d.ts.map +1 -1
  5. package/dist/utils/template.js +5 -0
  6. package/dist/utils/template.js.map +1 -1
  7. package/package.json +3 -2
  8. package/template/.env.example +103 -0
  9. package/template/components.json +22 -0
  10. package/template/docs/framework/01-overview.md +289 -0
  11. package/template/docs/framework/02-techstack.md +503 -0
  12. package/template/docs/framework/api-layer.md +681 -0
  13. package/template/docs/framework/clerk-authentication.md +649 -0
  14. package/template/docs/framework/cli-installation.md +564 -0
  15. package/template/docs/framework/deployment/ci-cd.md +907 -0
  16. package/template/docs/framework/deployment/digitalocean.md +991 -0
  17. package/template/docs/framework/deployment/domain-setup.md +972 -0
  18. package/template/docs/framework/deployment/environment-variables.md +863 -0
  19. package/template/docs/framework/deployment/monitoring.md +927 -0
  20. package/template/docs/framework/deployment/production-checklist.md +649 -0
  21. package/template/docs/framework/deployment/vercel.md +791 -0
  22. package/template/docs/framework/environment-variables.md +658 -0
  23. package/template/docs/framework/health-check-system.md +582 -0
  24. package/template/docs/framework/implementation.md +559 -0
  25. package/template/docs/framework/snowflake-integration.md +591 -0
  26. package/template/docs/framework/state-management.md +615 -0
  27. package/template/docs/framework/supabase-integration.md +581 -0
  28. package/template/docs/framework/testing-guide.md +544 -0
  29. package/template/docs/framework/what-did-i-miss.md +526 -0
  30. package/template/drizzle.config.ts +12 -0
  31. package/template/next.config.js +21 -0
  32. package/template/postcss.config.js +5 -0
  33. package/template/prettier.config.js +4 -0
  34. package/template/public/favicon.ico +0 -0
  35. package/template/src/app/(auth)/layout.tsx +4 -0
  36. package/template/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx +10 -0
  37. package/template/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx +10 -0
  38. package/template/src/app/(dashboard)/dashboard/page.tsx +8 -0
  39. package/template/src/app/(dashboard)/health/page.tsx +16 -0
  40. package/template/src/app/(dashboard)/layout.tsx +17 -0
  41. package/template/src/app/api/[[...route]]/route.ts +11 -0
  42. package/template/src/app/api/debug-files/route.ts +33 -0
  43. package/template/src/app/api/webhooks/clerk/route.ts +112 -0
  44. package/template/src/app/layout.tsx +28 -0
  45. package/template/src/app/page.tsx +12 -0
  46. package/template/src/app/providers.tsx +20 -0
  47. package/template/src/components/layouts/navbar.tsx +14 -0
  48. package/template/src/components/shared/loading-spinner.tsx +6 -0
  49. package/template/src/components/ui/badge.tsx +46 -0
  50. package/template/src/components/ui/button.tsx +62 -0
  51. package/template/src/components/ui/card.tsx +92 -0
  52. package/template/src/components/ui/collapsible.tsx +33 -0
  53. package/template/src/components/ui/scroll-area.tsx +58 -0
  54. package/template/src/components/ui/sheet.tsx +139 -0
  55. package/template/src/config/__tests__/env.test.ts +166 -0
  56. package/template/src/config/__tests__/site.test.ts +46 -0
  57. package/template/src/config/env.ts +36 -0
  58. package/template/src/config/site.ts +10 -0
  59. package/template/src/env.js +44 -0
  60. package/template/src/features/__tests__/health-check-config.test.ts +142 -0
  61. package/template/src/features/__tests__/health-check-types.test.ts +201 -0
  62. package/template/src/features/documentation/components/doc-sidebar.tsx +109 -0
  63. package/template/src/features/documentation/components/doc-viewer.tsx +70 -0
  64. package/template/src/features/documentation/index.tsx +92 -0
  65. package/template/src/features/documentation/utils/doc-loader.ts +177 -0
  66. package/template/src/features/health-check/components/health-dashboard.tsx +363 -0
  67. package/template/src/features/health-check/config.ts +72 -0
  68. package/template/src/features/health-check/index.ts +4 -0
  69. package/template/src/features/health-check/stores/health-store.ts +14 -0
  70. package/template/src/features/health-check/types.ts +18 -0
  71. package/template/src/hooks/__tests__/use-debounce.test.tsx +28 -0
  72. package/template/src/hooks/queries/use-health-checks.ts +16 -0
  73. package/template/src/hooks/utils/use-debounce.ts +20 -0
  74. package/template/src/lib/__tests__/utils.test.ts +52 -0
  75. package/template/src/lib/__tests__/validators.test.ts +114 -0
  76. package/template/src/lib/nextbank/client.ts +37 -0
  77. package/template/src/lib/snowflake/client.ts +53 -0
  78. package/template/src/lib/supabase/admin.ts +7 -0
  79. package/template/src/lib/supabase/client.ts +7 -0
  80. package/template/src/lib/supabase/server.ts +23 -0
  81. package/template/src/lib/utils.ts +6 -0
  82. package/template/src/lib/validators.ts +9 -0
  83. package/template/src/middleware.ts +22 -0
  84. package/template/src/server/api/index.ts +22 -0
  85. package/template/src/server/api/middleware/auth.ts +19 -0
  86. package/template/src/server/api/middleware/logger.ts +4 -0
  87. package/template/src/server/api/routes/health/clerk.ts +214 -0
  88. package/template/src/server/api/routes/health/database.ts +117 -0
  89. package/template/src/server/api/routes/health/edge-functions.ts +75 -0
  90. package/template/src/server/api/routes/health/framework.ts +45 -0
  91. package/template/src/server/api/routes/health/index.ts +102 -0
  92. package/template/src/server/api/routes/health/nextbank.ts +67 -0
  93. package/template/src/server/api/routes/health/snowflake.ts +83 -0
  94. package/template/src/server/api/routes/health/storage.ts +163 -0
  95. package/template/src/server/api/routes/users.ts +95 -0
  96. package/template/src/server/db/index.ts +17 -0
  97. package/template/src/server/db/queries/users.ts +8 -0
  98. package/template/src/server/db/schema/__tests__/health-checks.test.ts +31 -0
  99. package/template/src/server/db/schema/__tests__/users.test.ts +46 -0
  100. package/template/src/server/db/schema/health-checks.ts +11 -0
  101. package/template/src/server/db/schema/index.ts +2 -0
  102. package/template/src/server/db/schema/users.ts +16 -0
  103. package/template/src/server/db/schema.ts +26 -0
  104. package/template/src/stores/__tests__/ui-store.test.ts +87 -0
  105. package/template/src/stores/ui-store.ts +14 -0
  106. package/template/src/styles/globals.css +129 -0
  107. package/template/src/test/mocks/clerk.ts +35 -0
  108. package/template/src/test/mocks/snowflake.ts +28 -0
  109. package/template/src/test/mocks/supabase.ts +37 -0
  110. package/template/src/test/setup.ts +69 -0
  111. package/template/src/test/utils/test-helpers.ts +158 -0
  112. package/template/src/types/index.ts +14 -0
  113. package/template/tsconfig.json +43 -0
  114. package/template/vitest.config.ts +44 -0
@@ -0,0 +1,581 @@
1
+ # DTT Framework - Supabase Integration
2
+
3
+ ## Overview
4
+
5
+ The DTT Framework uses [Supabase](https://supabase.com/) as the primary database and storage solution. Supabase provides a PostgreSQL database, file storage, and edge functions, all managed through a single platform.
6
+
7
+ ### Why Supabase?
8
+
9
+ - **PostgreSQL**: Powerful, open-source relational database
10
+ - **Managed Service**: No database administration required
11
+ - **Real-time**: Real-time database subscriptions (not currently used)
12
+ - **Storage**: Built-in S3-compatible file storage
13
+ - **Edge Functions**: Serverless compute with Deno runtime
14
+ - **Open Source**: Self-hostable if needed
15
+ - **Connection Pooling**: Transaction mode for serverless optimization
16
+
17
+ ---
18
+
19
+ ## Database Setup with Drizzle ORM
20
+
21
+ ### 1. Create a Supabase Project
22
+
23
+ 1. Go to [supabase.com](https://supabase.com/) and sign up
24
+ 2. Create a new project
25
+ 3. Wait for the database to be provisioned
26
+ 4. Get your project URL and anon key from the dashboard
27
+
28
+ ### 2. Install Dependencies
29
+
30
+ ```bash
31
+ pnpm add drizzle-orm postgres @supabase/supabase-js @supabase/ssr
32
+ pnpm add -D drizzle-kit
33
+ ```
34
+
35
+ ### 3. Configure Environment Variables
36
+
37
+ Add the following to your [`.env`](./environment-variables.md) file:
38
+
39
+ ```bash
40
+ # Supabase
41
+ NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
42
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJxxx
43
+ SUPABASE_SERVICE_ROLE_KEY=eyJxxx
44
+ DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
45
+ ```
46
+
47
+ **Where to find these keys:**
48
+
49
+ - **Supabase URL**: Supabase Dashboard → Your Project → Settings → API → Project URL
50
+ - **Anon Key**: Supabase Dashboard → Your Project → Settings → API → anon/public key
51
+ - **Service Role Key**: Supabase Dashboard → Your Project → Settings → API → service_role key
52
+ - **Database URL**: Supabase Dashboard → Your Project → Settings → Database → Connection String → Transaction mode
53
+
54
+ ### 4. Configure Drizzle
55
+
56
+ Create [`drizzle.config.ts`](../../drizzle.config.ts):
57
+
58
+ ```typescript
59
+ import { defineConfig } from 'drizzle-kit'
60
+
61
+ export default defineConfig({
62
+ schema: './src/server/db/schema/index.ts',
63
+ out: './src/server/db/migrations',
64
+ dialect: 'postgresql',
65
+ dbCredentials: { url: process.env.DATABASE_URL! },
66
+ })
67
+ ```
68
+
69
+ ### 5. Create Database Client
70
+
71
+ Create [`src/server/db/index.ts`](../../src/server/db/index.ts):
72
+
73
+ ```typescript
74
+ import { drizzle } from 'drizzle-orm/postgres-js'
75
+ import postgres from 'postgres'
76
+ import { env } from '@/config/env'
77
+ import * as schema from './schema'
78
+
79
+ /**
80
+ * Cache the database connection in development. This avoids creating a new connection on every HMR
81
+ * update.
82
+ */
83
+ const globalForDb = globalThis as unknown as {
84
+ conn: postgres.Sql | undefined
85
+ }
86
+
87
+ const conn = globalForDb.conn ?? postgres(env.DATABASE_URL, { prepare: false })
88
+ if (env.NODE_ENV !== 'production') globalForDb.conn = conn
89
+
90
+ export const db = drizzle(conn, { schema })
91
+ ```
92
+
93
+ **Important:** The `prepare: false` option is required for Supabase Transaction mode connection pooling.
94
+
95
+ ### 6. Define Database Schema
96
+
97
+ Create schema files in [`src/server/db/schema/`](../../src/server/db/schema/):
98
+
99
+ **users.ts:**
100
+
101
+ ```typescript
102
+ import { pgTable, text, timestamp, varchar } from 'drizzle-orm/pg-core'
103
+
104
+ export const users = pgTable('users', {
105
+ id: text('id').primaryKey(), // Clerk user ID
106
+ email: varchar('email', { length: 255 }).notNull().unique(),
107
+ firstName: varchar('first_name', { length: 255 }),
108
+ lastName: varchar('last_name', { length: 255 }),
109
+ imageUrl: text('image_url'),
110
+ clerkOrgId: text('clerk_org_id'),
111
+ createdAt: timestamp('created_at').defaultNow().notNull(),
112
+ updatedAt: timestamp('updated_at').defaultNow().notNull(),
113
+ })
114
+
115
+ export type User = typeof users.$inferSelect
116
+ export type NewUser = typeof users.$inferInsert
117
+ ```
118
+
119
+ **health-checks.ts:**
120
+
121
+ ```typescript
122
+ import { pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core'
123
+
124
+ export const healthCheckTests = pgTable('health_check_tests', {
125
+ id: uuid('id').primaryKey().defaultRandom(),
126
+ testKey: text('test_key').notNull(),
127
+ testValue: text('test_value'),
128
+ createdAt: timestamp('created_at').defaultNow().notNull(),
129
+ })
130
+
131
+ export type HealthCheckTest = typeof healthCheckTests.$inferSelect
132
+ export type NewHealthCheckTest = typeof healthCheckTests.$inferInsert
133
+ ```
134
+
135
+ **index.ts:**
136
+
137
+ ```typescript
138
+ export * from './users'
139
+ export * from './health-checks'
140
+ ```
141
+
142
+ ### 7. Generate and Run Migrations
143
+
144
+ ```bash
145
+ # Generate migration files
146
+ pnpm db:generate
147
+
148
+ # Push schema to database (development)
149
+ pnpm db:push
150
+
151
+ # Or run migrations (production)
152
+ pnpm db:migrate
153
+ ```
154
+
155
+ ---
156
+
157
+ ## Storage Configuration
158
+
159
+ ### Supabase Storage Setup
160
+
161
+ ### 1. Create Storage Buckets
162
+
163
+ Go to Supabase Dashboard → Your Project → Storage → Create a new bucket:
164
+
165
+ - **Bucket Name**: `health-check-bucket` (or your preferred name)
166
+ - **Public Bucket**: No (for security)
167
+
168
+ ### 2. Configure Storage Clients
169
+
170
+ Create [`src/lib/supabase/client.ts`](../../src/lib/supabase/client.ts):
171
+
172
+ ```typescript
173
+ import { createClient } from '@supabase/supabase-js'
174
+ import { env } from '@/config/env'
175
+
176
+ export const supabase = createClient(
177
+ env.NEXT_PUBLIC_SUPABASE_URL,
178
+ env.NEXT_PUBLIC_SUPABASE_ANON_KEY
179
+ )
180
+ ```
181
+
182
+ Create [`src/lib/supabase/admin.ts`](../../src/lib/supabase/admin.ts):
183
+
184
+ ```typescript
185
+ import { createClient } from '@supabase/supabase-js'
186
+ import { env } from '@/config/env'
187
+
188
+ export const supabaseAdmin = createClient(
189
+ env.NEXT_PUBLIC_SUPABASE_URL,
190
+ env.SUPABASE_SERVICE_ROLE_KEY
191
+ )
192
+ ```
193
+
194
+ **Note:** Use `supabaseAdmin` for server-side operations that bypass RLS (Row Level Security).
195
+
196
+ ### 3. Storage Operations
197
+
198
+ **Upload a file:**
199
+
200
+ ```typescript
201
+ import { supabaseAdmin } from '@/lib/supabase/admin'
202
+
203
+ async function uploadFile(file: File, path: string) {
204
+ const { data, error } = await supabaseAdmin.storage
205
+ .from('your-bucket')
206
+ .upload(path, file, { upsert: true })
207
+
208
+ if (error) throw error
209
+ return data
210
+ }
211
+ ```
212
+
213
+ **Download a file (signed URL):**
214
+
215
+ ```typescript
216
+ async function getSignedUrl(path: string, expiresIn: number = 60) {
217
+ const { data, error } = await supabaseAdmin.storage
218
+ .from('your-bucket')
219
+ .createSignedUrl(path, expiresIn)
220
+
221
+ if (error) throw error
222
+ return data.signedUrl
223
+ }
224
+ ```
225
+
226
+ **Delete a file:**
227
+
228
+ ```typescript
229
+ async function deleteFile(path: string) {
230
+ const { error } = await supabaseAdmin.storage
231
+ .from('your-bucket')
232
+ .remove([path])
233
+
234
+ if (error) throw error
235
+ }
236
+ ```
237
+
238
+ **List files:**
239
+
240
+ ```typescript
241
+ async function listFiles(folder: string) {
242
+ const { data, error } = await supabaseAdmin.storage
243
+ .from('your-bucket')
244
+ .list(folder)
245
+
246
+ if (error) throw error
247
+ return data
248
+ }
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Edge Functions Setup
254
+
255
+ ### Supabase Edge Functions
256
+
257
+ Supabase Edge Functions are serverless functions that run on Deno at the edge. They're useful for:
258
+
259
+ - Background processing
260
+ - Webhook handling
261
+ - Third-party API integrations
262
+ - Custom business logic
263
+
264
+ ### 1. Install Supabase CLI
265
+
266
+ ```bash
267
+ pnpm add -g supabase
268
+ ```
269
+
270
+ ### 2. Initialize Edge Functions
271
+
272
+ ```bash
273
+ supabase functions deploy
274
+ ```
275
+
276
+ ### 3. Create an Edge Function
277
+
278
+ Create a function in `supabase/functions/your-function/index.ts`:
279
+
280
+ ```typescript
281
+ import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
282
+
283
+ serve(async (req) => {
284
+ const { method } = req
285
+
286
+ if (method === 'POST') {
287
+ const { name } = await req.json()
288
+
289
+ return new Response(
290
+ JSON.stringify({ message: `Hello, ${name}!` }),
291
+ { headers: { 'Content-Type': 'application/json' } }
292
+ )
293
+ }
294
+
295
+ return new Response('Method not allowed', { status: 405 })
296
+ })
297
+ ```
298
+
299
+ ### 4. Deploy Edge Functions
300
+
301
+ ```bash
302
+ supabase functions deploy your-function
303
+ ```
304
+
305
+ ### 5. Invoke Edge Functions
306
+
307
+ **From the application:**
308
+
309
+ ```typescript
310
+ import { supabaseAdmin } from '@/lib/supabase/admin'
311
+
312
+ async function invokeEdgeFunction(functionName: string, payload: any) {
313
+ const { data, error } = await supabaseAdmin.functions.invoke(functionName, {
314
+ body: payload,
315
+ })
316
+
317
+ if (error) throw error
318
+ return data
319
+ }
320
+ ```
321
+
322
+ ---
323
+
324
+ ## Connection Pooling Configuration
325
+
326
+ ### Supabase Connection Modes
327
+
328
+ Supabase offers two connection modes:
329
+
330
+ | Mode | Description | Use Case |
331
+ |------|-------------|----------|
332
+ | **Session Mode** | Direct connection to database | Serverful applications |
333
+ | **Transaction Mode** | Connection pooling | Serverless applications |
334
+
335
+ ### Transaction Mode (Recommended for Next.js)
336
+
337
+ The framework uses Transaction mode for optimal performance in serverless environments.
338
+
339
+ **Database URL Format:**
340
+
341
+ ```
342
+ postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
343
+ ```
344
+
345
+ **Key Points:**
346
+
347
+ - Uses `.pooler.supabase.com` domain
348
+ - Port `6543` instead of `5432`
349
+ - Requires `prepare: false` in postgres client
350
+
351
+ ### Connection Pooling Best Practices
352
+
353
+ 1. **Use Transaction Mode**: Always use transaction mode for serverless
354
+ 2. **Reuse Connections**: Cache connection in development (see [`src/server/db/index.ts`](../../src/server/db/index.ts))
355
+ 3. **Close Connections**: Connections are automatically closed when the lambda function terminates
356
+ 4. **Monitor Connections**: Check Supabase dashboard for connection usage
357
+
358
+ ---
359
+
360
+ ## Schema Management
361
+
362
+ ### Drizzle Migrations
363
+
364
+ ### Generate Migration
365
+
366
+ ```bash
367
+ pnpm db:generate
368
+ ```
369
+
370
+ This creates a new migration file in `src/server/db/migrations/`.
371
+
372
+ ### Push Schema (Development)
373
+
374
+ ```bash
375
+ pnpm db:push
376
+ ```
377
+
378
+ This pushes the schema directly to the database without creating a migration file. Useful for development.
379
+
380
+ ### Run Migrations (Production)
381
+
382
+ ```bash
383
+ pnpm db:migrate
384
+ ```
385
+
386
+ This applies all pending migrations to the database.
387
+
388
+ ### Rollback Migration
389
+
390
+ ```bash
391
+ drizzle-kit drop
392
+ ```
393
+
394
+ ### View Migrations
395
+
396
+ ```bash
397
+ drizzle-kit studio
398
+ ```
399
+
400
+ Opens Drizzle Studio to view and edit your database.
401
+
402
+ ---
403
+
404
+ ## Query Patterns
405
+
406
+ ### Basic Queries
407
+
408
+ **Select:**
409
+
410
+ ```typescript
411
+ import { db } from '@/server/db'
412
+ import { users } from '@/server/db/schema'
413
+
414
+ // Select all users
415
+ const allUsers = await db.select().from(users)
416
+
417
+ // Select with where
418
+ const user = await db.select().from(users).where(eq(users.id, userId))
419
+
420
+ // Select specific columns
421
+ const userEmails = await db.select({ email: users.email }).from(users)
422
+ ```
423
+
424
+ **Insert:**
425
+
426
+ ```typescript
427
+ // Insert single row
428
+ const newUser = await db.insert(users).values({
429
+ id: 'user_123',
430
+ email: 'user@example.com',
431
+ firstName: 'John',
432
+ lastName: 'Doe',
433
+ }).returning()
434
+
435
+ // Insert multiple rows
436
+ await db.insert(users).values([
437
+ { id: 'user_1', email: 'user1@example.com' },
438
+ { id: 'user_2', email: 'user2@example.com' },
439
+ ])
440
+ ```
441
+
442
+ **Update:**
443
+
444
+ ```typescript
445
+ await db.update(users)
446
+ .set({ firstName: 'Jane' })
447
+ .where(eq(users.id, userId))
448
+ ```
449
+
450
+ **Delete:**
451
+
452
+ ```typescript
453
+ await db.delete(users).where(eq(users.id, userId))
454
+ ```
455
+
456
+ ### Advanced Queries
457
+
458
+ **Joins:**
459
+
460
+ ```typescript
461
+ const result = await db
462
+ .select({
463
+ user: users,
464
+ // other tables...
465
+ })
466
+ .from(users)
467
+ .leftJoin(otherTable, eq(users.id, otherTable.userId))
468
+ ```
469
+
470
+ **Aggregations:**
471
+
472
+ ```typescript
473
+ const result = await db
474
+ .select({ count: sql<number>`count(*)` })
475
+ .from(users)
476
+ ```
477
+
478
+ **Transactions:**
479
+
480
+ ```typescript
481
+ await db.transaction(async (tx) => {
482
+ await tx.insert(users).values({ id: 'user_1', email: 'user1@example.com' })
483
+ await tx.insert(users).values({ id: 'user_2', email: 'user2@example.com' })
484
+ })
485
+ ```
486
+
487
+ ---
488
+
489
+ ## Health Check Endpoints
490
+
491
+ The framework includes health check endpoints for verifying Supabase integration:
492
+
493
+ ### Database Health Checks
494
+
495
+ | Endpoint | Method | Description |
496
+ |----------|--------|-------------|
497
+ | `/api/health/database/write` | POST | Write test row to database |
498
+ | `/api/health/database/read` | GET | Read test row from database |
499
+ | `/api/health/database/delete` | DELETE | Delete test row from database |
500
+
501
+ ### Storage Health Checks
502
+
503
+ | Endpoint | Method | Description |
504
+ |----------|--------|-------------|
505
+ | `/api/health/storage/upload` | POST | Upload test file to storage |
506
+ | `/api/health/storage/download` | GET | Generate signed URL for test file |
507
+ | `/api/health/storage/delete` | DELETE | Delete test file from storage |
508
+
509
+ ### Edge Functions Health Checks
510
+
511
+ | Endpoint | Method | Description |
512
+ |----------|--------|-------------|
513
+ | `/api/health/edge/ping` | GET | Ping edge function (placeholder) |
514
+ | `/api/health/edge/auth` | GET | Test auth header passthrough (placeholder) |
515
+
516
+ ---
517
+
518
+ ## Security Considerations
519
+
520
+ ### Row Level Security (RLS)
521
+
522
+ Supabase provides Row Level Security to control data access:
523
+
524
+ 1. Enable RLS on tables in Supabase Dashboard
525
+ 2. Create policies to control access
526
+ 3. Use `supabase` client (not `supabaseAdmin`) for client-side queries
527
+
528
+ ### Service Role Key
529
+
530
+ The `SUPABASE_SERVICE_ROLE_KEY` bypasses RLS:
531
+
532
+ - **Use**: Server-side operations that need full access
533
+ - **Never expose**: This key should never be in client code
534
+ - **Store securely**: Keep in environment variables only
535
+
536
+ ### Anon Key
537
+
538
+ The `NEXT_PUBLIC_SUPABASE_ANON_KEY` is safe to expose:
539
+
540
+ - **Use**: Client-side queries
541
+ - **Limited access**: Respects RLS policies
542
+ - **Can be exposed**: Safe to include in client bundles
543
+
544
+ ---
545
+
546
+ ## Troubleshooting
547
+
548
+ ### Common Issues
549
+
550
+ **Issue: Connection timeout**
551
+
552
+ - Verify `DATABASE_URL` is correct
553
+ - Check if you're using the correct connection mode (Transaction vs Session)
554
+ - Verify port is `6543` for Transaction mode
555
+
556
+ **Issue: "prepare: false" error**
557
+
558
+ - Ensure `prepare: false` is set in the postgres client
559
+ - This is required for Supabase Transaction mode
560
+
561
+ **Issue: Storage upload fails**
562
+
563
+ - Check if bucket exists
564
+ - Verify bucket permissions
565
+ - Ensure `supabaseAdmin` is used for server-side uploads
566
+
567
+ **Issue: Migration fails**
568
+
569
+ - Verify `DATABASE_URL` is set correctly
570
+ - Check if database is accessible
571
+ - Ensure you have write permissions
572
+
573
+ ---
574
+
575
+ ## Related Documentation
576
+
577
+ - [Environment Variables](./environment-variables.md) - Supabase environment variables
578
+ - [Clerk Authentication](./clerk-authentication.md) - User schema and webhooks
579
+ - [API Layer](./api-layer.md) - Database queries in API routes
580
+ - [Health Check System](./health-check-system.md) - Health check endpoints
581
+ - [Snowflake Integration](./snowflake-integration.md) - Data warehouse integration