@odvi/create-dtt-framework 0.1.3 → 0.1.6

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