@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.
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +16 -13
- package/dist/commands/create.js.map +1 -1
- package/dist/utils/template.d.ts.map +1 -1
- package/dist/utils/template.js +5 -0
- package/dist/utils/template.js.map +1 -1
- package/package.json +3 -2
- package/template/.env.example +103 -0
- package/template/components.json +22 -0
- package/template/docs/framework/01-overview.md +289 -0
- package/template/docs/framework/02-techstack.md +503 -0
- package/template/docs/framework/api-layer.md +681 -0
- package/template/docs/framework/clerk-authentication.md +649 -0
- package/template/docs/framework/cli-installation.md +564 -0
- package/template/docs/framework/deployment/ci-cd.md +907 -0
- package/template/docs/framework/deployment/digitalocean.md +991 -0
- package/template/docs/framework/deployment/domain-setup.md +972 -0
- package/template/docs/framework/deployment/environment-variables.md +863 -0
- package/template/docs/framework/deployment/monitoring.md +927 -0
- package/template/docs/framework/deployment/production-checklist.md +649 -0
- package/template/docs/framework/deployment/vercel.md +791 -0
- package/template/docs/framework/environment-variables.md +658 -0
- package/template/docs/framework/health-check-system.md +582 -0
- package/template/docs/framework/implementation.md +559 -0
- package/template/docs/framework/snowflake-integration.md +591 -0
- package/template/docs/framework/state-management.md +615 -0
- package/template/docs/framework/supabase-integration.md +581 -0
- package/template/docs/framework/testing-guide.md +544 -0
- package/template/docs/framework/what-did-i-miss.md +526 -0
- package/template/drizzle.config.ts +12 -0
- package/template/next.config.js +21 -0
- package/template/postcss.config.js +5 -0
- package/template/prettier.config.js +4 -0
- package/template/public/favicon.ico +0 -0
- package/template/src/app/(auth)/layout.tsx +4 -0
- package/template/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx +10 -0
- package/template/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx +10 -0
- package/template/src/app/(dashboard)/dashboard/page.tsx +8 -0
- package/template/src/app/(dashboard)/health/page.tsx +16 -0
- package/template/src/app/(dashboard)/layout.tsx +17 -0
- package/template/src/app/api/[[...route]]/route.ts +11 -0
- package/template/src/app/api/debug-files/route.ts +33 -0
- package/template/src/app/api/webhooks/clerk/route.ts +112 -0
- package/template/src/app/layout.tsx +28 -0
- package/template/src/app/page.tsx +12 -0
- package/template/src/app/providers.tsx +20 -0
- package/template/src/components/layouts/navbar.tsx +14 -0
- package/template/src/components/shared/loading-spinner.tsx +6 -0
- package/template/src/components/ui/badge.tsx +46 -0
- package/template/src/components/ui/button.tsx +62 -0
- package/template/src/components/ui/card.tsx +92 -0
- package/template/src/components/ui/collapsible.tsx +33 -0
- package/template/src/components/ui/scroll-area.tsx +58 -0
- package/template/src/components/ui/sheet.tsx +139 -0
- package/template/src/config/__tests__/env.test.ts +166 -0
- package/template/src/config/__tests__/site.test.ts +46 -0
- package/template/src/config/env.ts +36 -0
- package/template/src/config/site.ts +10 -0
- package/template/src/env.js +44 -0
- package/template/src/features/__tests__/health-check-config.test.ts +142 -0
- package/template/src/features/__tests__/health-check-types.test.ts +201 -0
- package/template/src/features/documentation/components/doc-sidebar.tsx +109 -0
- package/template/src/features/documentation/components/doc-viewer.tsx +70 -0
- package/template/src/features/documentation/index.tsx +92 -0
- package/template/src/features/documentation/utils/doc-loader.ts +177 -0
- package/template/src/features/health-check/components/health-dashboard.tsx +363 -0
- package/template/src/features/health-check/config.ts +72 -0
- package/template/src/features/health-check/index.ts +4 -0
- package/template/src/features/health-check/stores/health-store.ts +14 -0
- package/template/src/features/health-check/types.ts +18 -0
- package/template/src/hooks/__tests__/use-debounce.test.tsx +28 -0
- package/template/src/hooks/queries/use-health-checks.ts +16 -0
- package/template/src/hooks/utils/use-debounce.ts +20 -0
- package/template/src/lib/__tests__/utils.test.ts +52 -0
- package/template/src/lib/__tests__/validators.test.ts +114 -0
- package/template/src/lib/nextbank/client.ts +37 -0
- package/template/src/lib/snowflake/client.ts +53 -0
- package/template/src/lib/supabase/admin.ts +7 -0
- package/template/src/lib/supabase/client.ts +7 -0
- package/template/src/lib/supabase/server.ts +23 -0
- package/template/src/lib/utils.ts +6 -0
- package/template/src/lib/validators.ts +9 -0
- package/template/src/middleware.ts +22 -0
- package/template/src/server/api/index.ts +22 -0
- package/template/src/server/api/middleware/auth.ts +19 -0
- package/template/src/server/api/middleware/logger.ts +4 -0
- package/template/src/server/api/routes/health/clerk.ts +214 -0
- package/template/src/server/api/routes/health/database.ts +117 -0
- package/template/src/server/api/routes/health/edge-functions.ts +75 -0
- package/template/src/server/api/routes/health/framework.ts +45 -0
- package/template/src/server/api/routes/health/index.ts +102 -0
- package/template/src/server/api/routes/health/nextbank.ts +67 -0
- package/template/src/server/api/routes/health/snowflake.ts +83 -0
- package/template/src/server/api/routes/health/storage.ts +163 -0
- package/template/src/server/api/routes/users.ts +95 -0
- package/template/src/server/db/index.ts +17 -0
- package/template/src/server/db/queries/users.ts +8 -0
- package/template/src/server/db/schema/__tests__/health-checks.test.ts +31 -0
- package/template/src/server/db/schema/__tests__/users.test.ts +46 -0
- package/template/src/server/db/schema/health-checks.ts +11 -0
- package/template/src/server/db/schema/index.ts +2 -0
- package/template/src/server/db/schema/users.ts +16 -0
- package/template/src/server/db/schema.ts +26 -0
- package/template/src/stores/__tests__/ui-store.test.ts +87 -0
- package/template/src/stores/ui-store.ts +14 -0
- package/template/src/styles/globals.css +129 -0
- package/template/src/test/mocks/clerk.ts +35 -0
- package/template/src/test/mocks/snowflake.ts +28 -0
- package/template/src/test/mocks/supabase.ts +37 -0
- package/template/src/test/setup.ts +69 -0
- package/template/src/test/utils/test-helpers.ts +158 -0
- package/template/src/types/index.ts +14 -0
- package/template/tsconfig.json +43 -0
- package/template/vitest.config.ts +44 -0
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
# DTT Framework - Environment Variables
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Environment variables are used to configure the DTT Framework. This document provides a complete reference for all available environment variables, their purposes, and how to configure them.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Complete .env.example Reference
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# ============================================
|
|
13
|
+
# DTT Framework Environment Variables
|
|
14
|
+
# ============================================
|
|
15
|
+
# Copy this file to .env and fill in your values
|
|
16
|
+
# Never commit .env to version control
|
|
17
|
+
# ============================================
|
|
18
|
+
|
|
19
|
+
# ============================================
|
|
20
|
+
# Application
|
|
21
|
+
# ============================================
|
|
22
|
+
|
|
23
|
+
# The URL where your application is deployed
|
|
24
|
+
# Used for redirects, webhooks, and callbacks
|
|
25
|
+
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
26
|
+
|
|
27
|
+
# ============================================
|
|
28
|
+
# Clerk Authentication
|
|
29
|
+
# ============================================
|
|
30
|
+
|
|
31
|
+
# Clerk publishable key (starts with pk_)
|
|
32
|
+
# Used for client-side Clerk operations
|
|
33
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxx
|
|
34
|
+
|
|
35
|
+
# Clerk secret key (starts with sk_)
|
|
36
|
+
# Used for server-side Clerk operations
|
|
37
|
+
CLERK_SECRET_KEY=sk_test_xxx
|
|
38
|
+
|
|
39
|
+
# Clerk webhook secret (starts with whsec_)
|
|
40
|
+
# Used to verify webhook signatures
|
|
41
|
+
CLERK_WEBHOOK_SECRET=whsec_xxx
|
|
42
|
+
|
|
43
|
+
# URL for sign-in page
|
|
44
|
+
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
|
|
45
|
+
|
|
46
|
+
# URL for sign-up page
|
|
47
|
+
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
|
|
48
|
+
|
|
49
|
+
# Redirect URL after successful sign-in
|
|
50
|
+
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/health
|
|
51
|
+
|
|
52
|
+
# Redirect URL after successful sign-up
|
|
53
|
+
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/health
|
|
54
|
+
|
|
55
|
+
# ============================================
|
|
56
|
+
# Supabase
|
|
57
|
+
# ============================================
|
|
58
|
+
|
|
59
|
+
# Supabase project URL
|
|
60
|
+
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
|
|
61
|
+
|
|
62
|
+
# Supabase anonymous/public key
|
|
63
|
+
# Used for client-side Supabase operations
|
|
64
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJxxx
|
|
65
|
+
|
|
66
|
+
# Supabase service role key
|
|
67
|
+
# Used for server-side Supabase operations (bypasses RLS)
|
|
68
|
+
SUPABASE_SERVICE_ROLE_KEY=eyJxxx
|
|
69
|
+
|
|
70
|
+
# PostgreSQL connection URL (Transaction mode)
|
|
71
|
+
# Format: postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
|
|
72
|
+
DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
|
|
73
|
+
|
|
74
|
+
# ============================================
|
|
75
|
+
# Snowflake (Optional)
|
|
76
|
+
# ============================================
|
|
77
|
+
|
|
78
|
+
# Snowflake account identifier
|
|
79
|
+
# Format: [account_locator].[region]
|
|
80
|
+
SNOWFLAKE_ACCOUNT=xxx.us-east-1
|
|
81
|
+
|
|
82
|
+
# Snowflake username
|
|
83
|
+
SNOWFLAKE_USERNAME=xxx
|
|
84
|
+
|
|
85
|
+
# Snowflake password
|
|
86
|
+
SNOWFLAKE_PASSWORD=xxx
|
|
87
|
+
|
|
88
|
+
# Snowflake warehouse name
|
|
89
|
+
SNOWFLAKE_WAREHOUSE=COMPUTE_WH
|
|
90
|
+
|
|
91
|
+
# Snowflake database name
|
|
92
|
+
SNOWFLAKE_DATABASE=ANALYTICS
|
|
93
|
+
|
|
94
|
+
# Snowflake schema name
|
|
95
|
+
SNOWFLAKE_SCHEMA=PUBLIC
|
|
96
|
+
|
|
97
|
+
# Snowflake role name
|
|
98
|
+
SNOWFLAKE_ROLE=ANALYST
|
|
99
|
+
|
|
100
|
+
# ============================================
|
|
101
|
+
# NextBank (Placeholder - Optional)
|
|
102
|
+
# ============================================
|
|
103
|
+
|
|
104
|
+
# NextBank API URL
|
|
105
|
+
NEXTBANK_API_URL=https://api.nextbank.com
|
|
106
|
+
|
|
107
|
+
# NextBank API key
|
|
108
|
+
NEXTBANK_API_KEY=xxx
|
|
109
|
+
|
|
110
|
+
# NextBank OAuth client ID
|
|
111
|
+
NEXTBANK_CLIENT_ID=xxx
|
|
112
|
+
|
|
113
|
+
# NextBank OAuth client secret
|
|
114
|
+
NEXTBANK_CLIENT_SECRET=xxx
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## How to Configure Each Variable
|
|
120
|
+
|
|
121
|
+
### Application Variables
|
|
122
|
+
|
|
123
|
+
#### NEXT_PUBLIC_APP_URL
|
|
124
|
+
|
|
125
|
+
**Purpose:** Base URL for your application
|
|
126
|
+
|
|
127
|
+
**Where to find:** This is your application's URL
|
|
128
|
+
|
|
129
|
+
**Examples:**
|
|
130
|
+
```bash
|
|
131
|
+
# Development
|
|
132
|
+
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
133
|
+
|
|
134
|
+
# Production
|
|
135
|
+
NEXT_PUBLIC_APP_URL=https://your-app.com
|
|
136
|
+
|
|
137
|
+
# Staging
|
|
138
|
+
NEXT_PUBLIC_APP_URL=https://staging.your-app.com
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Notes:**
|
|
142
|
+
- Must include protocol (http:// or https://)
|
|
143
|
+
- No trailing slash
|
|
144
|
+
- Used for webhook callbacks and redirects
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### Clerk Authentication Variables
|
|
149
|
+
|
|
150
|
+
#### NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
|
|
151
|
+
|
|
152
|
+
**Purpose:** Client-side Clerk operations
|
|
153
|
+
|
|
154
|
+
**Where to find:** Clerk Dashboard → Your App → API Keys → Publishable Key
|
|
155
|
+
|
|
156
|
+
**Format:** Starts with `pk_`
|
|
157
|
+
|
|
158
|
+
**Example:**
|
|
159
|
+
```bash
|
|
160
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxx
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Notes:**
|
|
164
|
+
- Safe to expose to client (starts with NEXT_PUBLIC_)
|
|
165
|
+
- Used for Clerk components on client-side
|
|
166
|
+
- Different keys for test and production environments
|
|
167
|
+
|
|
168
|
+
#### CLERK_SECRET_KEY
|
|
169
|
+
|
|
170
|
+
**Purpose:** Server-side Clerk operations
|
|
171
|
+
|
|
172
|
+
**Where to find:** Clerk Dashboard → Your App → API Keys → Secret Key
|
|
173
|
+
|
|
174
|
+
**Format:** Starts with `sk_`
|
|
175
|
+
|
|
176
|
+
**Example:**
|
|
177
|
+
```bash
|
|
178
|
+
CLERK_SECRET_KEY=sk_test_xxx
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Notes:**
|
|
182
|
+
- Never expose to client (no NEXT_PUBLIC_ prefix)
|
|
183
|
+
- Used for server-side auth verification
|
|
184
|
+
- Keep secret and never commit to version control
|
|
185
|
+
|
|
186
|
+
#### CLERK_WEBHOOK_SECRET
|
|
187
|
+
|
|
188
|
+
**Purpose:** Verify webhook signatures
|
|
189
|
+
|
|
190
|
+
**Where to find:** Clerk Dashboard → Your App → Webhooks → Add Endpoint → Copy Secret
|
|
191
|
+
|
|
192
|
+
**Format:** Starts with `whsec_`
|
|
193
|
+
|
|
194
|
+
**Example:**
|
|
195
|
+
```bash
|
|
196
|
+
CLERK_WEBHOOK_SECRET=whsec_xxx
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Notes:**
|
|
200
|
+
- Never expose to client
|
|
201
|
+
- Used to verify incoming webhooks are from Clerk
|
|
202
|
+
- Required for webhook endpoint
|
|
203
|
+
|
|
204
|
+
#### Clerk URL Variables
|
|
205
|
+
|
|
206
|
+
**Purpose:** Configure Clerk authentication flow
|
|
207
|
+
|
|
208
|
+
**Examples:**
|
|
209
|
+
```bash
|
|
210
|
+
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
|
|
211
|
+
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
|
|
212
|
+
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/health
|
|
213
|
+
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/health
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Notes:**
|
|
217
|
+
- All start with NEXT_PUBLIC_ (used in client)
|
|
218
|
+
- Can be absolute URLs or relative paths
|
|
219
|
+
- Customize based on your routing structure
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Supabase Variables
|
|
224
|
+
|
|
225
|
+
#### NEXT_PUBLIC_SUPABASE_URL
|
|
226
|
+
|
|
227
|
+
**Purpose:** Supabase project URL
|
|
228
|
+
|
|
229
|
+
**Where to find:** Supabase Dashboard → Your Project → Settings → API → Project URL
|
|
230
|
+
|
|
231
|
+
**Format:** Full URL including protocol
|
|
232
|
+
|
|
233
|
+
**Example:**
|
|
234
|
+
```bash
|
|
235
|
+
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Notes:**
|
|
239
|
+
- Safe to expose to client
|
|
240
|
+
- Used for all Supabase client operations
|
|
241
|
+
- Different URL for each project
|
|
242
|
+
|
|
243
|
+
#### NEXT_PUBLIC_SUPABASE_ANON_KEY
|
|
244
|
+
|
|
245
|
+
**Purpose:** Client-side Supabase operations
|
|
246
|
+
|
|
247
|
+
**Where to find:** Supabase Dashboard → Your Project → Settings → API → anon/public key
|
|
248
|
+
|
|
249
|
+
**Format:** JWT token (starts with `eyJ`)
|
|
250
|
+
|
|
251
|
+
**Example:**
|
|
252
|
+
```bash
|
|
253
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJxxx
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Notes:**
|
|
257
|
+
- Safe to expose to client
|
|
258
|
+
- Respects Row Level Security (RLS) policies
|
|
259
|
+
- Limited permissions by default
|
|
260
|
+
|
|
261
|
+
#### SUPABASE_SERVICE_ROLE_KEY
|
|
262
|
+
|
|
263
|
+
**Purpose:** Server-side Supabase operations with full access
|
|
264
|
+
|
|
265
|
+
**Where to find:** Supabase Dashboard → Your Project → Settings → API → service_role key
|
|
266
|
+
|
|
267
|
+
**Format:** JWT token (starts with `eyJ`)
|
|
268
|
+
|
|
269
|
+
**Example:**
|
|
270
|
+
```bash
|
|
271
|
+
SUPABASE_SERVICE_ROLE_KEY=eyJxxx
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Notes:**
|
|
275
|
+
- Never expose to client
|
|
276
|
+
- Bypasses Row Level Security (RLS)
|
|
277
|
+
- Full database access
|
|
278
|
+
- Use only on server-side
|
|
279
|
+
|
|
280
|
+
#### DATABASE_URL
|
|
281
|
+
|
|
282
|
+
**Purpose:** PostgreSQL connection string
|
|
283
|
+
|
|
284
|
+
**Where to find:** Supabase Dashboard → Your Project → Settings → Database → Connection String → Transaction mode
|
|
285
|
+
|
|
286
|
+
**Format:** PostgreSQL connection string
|
|
287
|
+
|
|
288
|
+
**Example:**
|
|
289
|
+
```bash
|
|
290
|
+
DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Notes:**
|
|
294
|
+
- Never expose to client
|
|
295
|
+
- Use Transaction mode for serverless (port 6543, .pooler. domain)
|
|
296
|
+
- Required for Drizzle ORM
|
|
297
|
+
- Format: `postgresql://[user]:[password]@[host]:[port]/[database]`
|
|
298
|
+
|
|
299
|
+
**Connection Modes:**
|
|
300
|
+
|
|
301
|
+
| Mode | URL Format | Use Case |
|
|
302
|
+
|-------|-------------|----------|
|
|
303
|
+
| **Session** | `postgres://[user]:[password]@[host]:5432/[database]` | Serverful applications |
|
|
304
|
+
| **Transaction** | `postgres://[user]:[password]@[host]:6543/[database]` | Serverless applications |
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
### Snowflake Variables (Optional)
|
|
309
|
+
|
|
310
|
+
#### SNOWFLAKE_ACCOUNT
|
|
311
|
+
|
|
312
|
+
**Purpose:** Snowflake account identifier
|
|
313
|
+
|
|
314
|
+
**Where to find:** Snowflake URL when logged in
|
|
315
|
+
|
|
316
|
+
**Format:** `[account_locator].[region]`
|
|
317
|
+
|
|
318
|
+
**Example:**
|
|
319
|
+
```bash
|
|
320
|
+
SNOWFLAKE_ACCOUNT=xy12345.us-east-1
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Notes:**
|
|
324
|
+
- Extract from Snowflake URL: `https://xy12345.us-east-1.snowflakecomputing.com`
|
|
325
|
+
- Different regions: `us-east-1`, `us-west-2`, `eu-west-1`, etc.
|
|
326
|
+
|
|
327
|
+
#### SNOWFLAKE_USERNAME
|
|
328
|
+
|
|
329
|
+
**Purpose:** Snowflake username
|
|
330
|
+
|
|
331
|
+
**Where to find:** Your Snowflake username
|
|
332
|
+
|
|
333
|
+
**Example:**
|
|
334
|
+
```bash
|
|
335
|
+
SNOWFLAKE_USERNAME=myuser
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Notes:**
|
|
339
|
+
- Case-sensitive
|
|
340
|
+
- Usually email or custom username
|
|
341
|
+
|
|
342
|
+
#### SNOWFLAKE_PASSWORD
|
|
343
|
+
|
|
344
|
+
**Purpose:** Snowflake password
|
|
345
|
+
|
|
346
|
+
**Where to find:** Your Snowflake password
|
|
347
|
+
|
|
348
|
+
**Example:**
|
|
349
|
+
```bash
|
|
350
|
+
SNOWFLAKE_PASSWORD=mypassword
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**Notes:**
|
|
354
|
+
- Never commit to version control
|
|
355
|
+
- May need to be updated if password changes
|
|
356
|
+
- Consider using password rotation policies
|
|
357
|
+
|
|
358
|
+
#### SNOWFLAKE_WAREHOUSE
|
|
359
|
+
|
|
360
|
+
**Purpose:** Compute warehouse to use
|
|
361
|
+
|
|
362
|
+
**Where to find:** Snowflake → Warehouses
|
|
363
|
+
|
|
364
|
+
**Example:**
|
|
365
|
+
```bash
|
|
366
|
+
SNOWFLAKE_WAREHOUSE=COMPUTE_WH
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**Notes:**
|
|
370
|
+
- Warehouse must exist in your Snowflake account
|
|
371
|
+
- Different sizes: X-Small, Small, Medium, Large, etc.
|
|
372
|
+
- Affects query performance and cost
|
|
373
|
+
|
|
374
|
+
#### SNOWFLAKE_DATABASE
|
|
375
|
+
|
|
376
|
+
**Purpose:** Database to connect to
|
|
377
|
+
|
|
378
|
+
**Where to find:** Snowflake → Databases
|
|
379
|
+
|
|
380
|
+
**Example:**
|
|
381
|
+
```bash
|
|
382
|
+
SNOWFLAKE_DATABASE=ANALYTICS
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
**Notes:**
|
|
386
|
+
- Database must exist in your Snowflake account
|
|
387
|
+
- User must have access to database
|
|
388
|
+
- Default is often `SNOWFLAKE` or `ANALYTICS`
|
|
389
|
+
|
|
390
|
+
#### SNOWFLAKE_SCHEMA
|
|
391
|
+
|
|
392
|
+
**Purpose:** Schema to use
|
|
393
|
+
|
|
394
|
+
**Where to find:** Snowflake → Databases → Your Database → Schemas
|
|
395
|
+
|
|
396
|
+
**Example:**
|
|
397
|
+
```bash
|
|
398
|
+
SNOWFLAKE_SCHEMA=PUBLIC
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
**Notes:**
|
|
402
|
+
- Schema must exist in database
|
|
403
|
+
- Default is usually `PUBLIC`
|
|
404
|
+
- User must have access to schema
|
|
405
|
+
|
|
406
|
+
#### SNOWFLAKE_ROLE
|
|
407
|
+
|
|
408
|
+
**Purpose:** Role to use for queries
|
|
409
|
+
|
|
410
|
+
**Where to find:** Snowflake → Roles
|
|
411
|
+
|
|
412
|
+
**Example:**
|
|
413
|
+
```bash
|
|
414
|
+
SNOWFLAKE_ROLE=ANALYST
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**Notes:**
|
|
418
|
+
- Role must exist in your Snowflake account
|
|
419
|
+
- User must be granted the role
|
|
420
|
+
- Determines permissions and access
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### NextBank Variables (Placeholder)
|
|
425
|
+
|
|
426
|
+
**Note:** NextBank is a placeholder integration. These variables are optional and not currently used.
|
|
427
|
+
|
|
428
|
+
#### NEXTBANK_API_URL
|
|
429
|
+
|
|
430
|
+
**Purpose:** NextBank API endpoint
|
|
431
|
+
|
|
432
|
+
**Example:**
|
|
433
|
+
```bash
|
|
434
|
+
NEXTBANK_API_URL=https://api.nextbank.com
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
#### NEXTBANK_API_KEY
|
|
438
|
+
|
|
439
|
+
**Purpose:** API key for NextBank
|
|
440
|
+
|
|
441
|
+
**Example:**
|
|
442
|
+
```bash
|
|
443
|
+
NEXTBANK_API_KEY=xxx
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
#### NEXTBANK_CLIENT_ID
|
|
447
|
+
|
|
448
|
+
**Purpose:** OAuth client ID
|
|
449
|
+
|
|
450
|
+
**Example:**
|
|
451
|
+
```bash
|
|
452
|
+
NEXTBANK_CLIENT_ID=xxx
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
#### NEXTBANK_CLIENT_SECRET
|
|
456
|
+
|
|
457
|
+
**Purpose:** OAuth client secret
|
|
458
|
+
|
|
459
|
+
**Example:**
|
|
460
|
+
```bash
|
|
461
|
+
NEXTBANK_CLIENT_SECRET=xxx
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## Security Considerations
|
|
467
|
+
|
|
468
|
+
### 1. Never Commit .env Files
|
|
469
|
+
|
|
470
|
+
Always add `.env` to `.gitignore`:
|
|
471
|
+
|
|
472
|
+
```gitignore
|
|
473
|
+
# Environment variables
|
|
474
|
+
.env
|
|
475
|
+
.env.local
|
|
476
|
+
.env.development.local
|
|
477
|
+
.env.test.local
|
|
478
|
+
.env.production.local
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### 2. Use Environment-Specific Files
|
|
482
|
+
|
|
483
|
+
Use different environment files for different stages:
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
# Development
|
|
487
|
+
.env.development
|
|
488
|
+
|
|
489
|
+
# Staging
|
|
490
|
+
.env.staging
|
|
491
|
+
|
|
492
|
+
# Production
|
|
493
|
+
.env.production
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Load appropriate file based on environment:
|
|
497
|
+
|
|
498
|
+
```bash
|
|
499
|
+
# In package.json scripts
|
|
500
|
+
"dev": "cp .env.development .env && next dev",
|
|
501
|
+
"build": "cp .env.production .env && next build"
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### 3. Prefix Client Variables
|
|
505
|
+
|
|
506
|
+
Only prefix variables with `NEXT_PUBLIC_` if they need to be exposed to client:
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
# ✅ Good - Exposed to client
|
|
510
|
+
NEXT_PUBLIC_API_URL=https://api.example.com
|
|
511
|
+
|
|
512
|
+
# ❌ Bad - Not exposed, but might be needed
|
|
513
|
+
API_URL=https://api.example.com
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### 4. Validate Environment Variables
|
|
517
|
+
|
|
518
|
+
The framework uses `@t3-oss/env-nextjs` for validation:
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
// src/config/env.ts
|
|
522
|
+
export const env = createEnv({
|
|
523
|
+
server: {
|
|
524
|
+
DATABASE_URL: z.string().url(),
|
|
525
|
+
CLERK_SECRET_KEY: z.string().startsWith('sk_'),
|
|
526
|
+
},
|
|
527
|
+
client: {
|
|
528
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().startsWith('pk_'),
|
|
529
|
+
},
|
|
530
|
+
})
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
This ensures:
|
|
534
|
+
- All required variables are present
|
|
535
|
+
- Variables are correctly formatted
|
|
536
|
+
- Build fails if variables are missing
|
|
537
|
+
|
|
538
|
+
### 5. Use Secret Management Services
|
|
539
|
+
|
|
540
|
+
For production, consider using secret management:
|
|
541
|
+
|
|
542
|
+
- **Vercel Environment Variables**: For Vercel deployments
|
|
543
|
+
- **AWS Secrets Manager**: For AWS deployments
|
|
544
|
+
- **GitHub Secrets**: For GitHub Actions
|
|
545
|
+
- **Docker Secrets**: For containerized deployments
|
|
546
|
+
|
|
547
|
+
---
|
|
548
|
+
|
|
549
|
+
## Environment Variable Validation
|
|
550
|
+
|
|
551
|
+
### Schema Validation
|
|
552
|
+
|
|
553
|
+
The framework validates environment variables at build time:
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
// src/config/env.ts
|
|
557
|
+
import { createEnv } from '@t3-oss/env-nextjs'
|
|
558
|
+
import { z } from 'zod'
|
|
559
|
+
|
|
560
|
+
export const env = createEnv({
|
|
561
|
+
server: {
|
|
562
|
+
DATABASE_URL: z.string().url(),
|
|
563
|
+
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
|
|
564
|
+
},
|
|
565
|
+
client: {
|
|
566
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().startsWith('pk_'),
|
|
567
|
+
},
|
|
568
|
+
runtimeEnv: {
|
|
569
|
+
DATABASE_URL: process.env.DATABASE_URL,
|
|
570
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
571
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
|
|
572
|
+
},
|
|
573
|
+
})
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### Validation Errors
|
|
577
|
+
|
|
578
|
+
If validation fails, you'll see an error like:
|
|
579
|
+
|
|
580
|
+
```
|
|
581
|
+
❌ Invalid environment variables:
|
|
582
|
+
- DATABASE_URL: Required
|
|
583
|
+
- NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: Must start with "pk_"
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### Skipping Validation
|
|
587
|
+
|
|
588
|
+
For Docker builds, you can skip validation:
|
|
589
|
+
|
|
590
|
+
```bash
|
|
591
|
+
SKIP_ENV_VALIDATION=true pnpm build
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
## Troubleshooting
|
|
597
|
+
|
|
598
|
+
### Common Issues
|
|
599
|
+
|
|
600
|
+
**Issue: "Environment variable not found"**
|
|
601
|
+
|
|
602
|
+
**Solution:** Ensure `.env` file exists and is loaded:
|
|
603
|
+
|
|
604
|
+
```bash
|
|
605
|
+
# Check if .env exists
|
|
606
|
+
ls -la .env
|
|
607
|
+
|
|
608
|
+
# Copy from example if missing
|
|
609
|
+
cp .env.example .env
|
|
610
|
+
|
|
611
|
+
# Restart development server
|
|
612
|
+
pnpm dev
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
**Issue: "Invalid environment variable format"**
|
|
616
|
+
|
|
617
|
+
**Solution:** Check variable format matches expected pattern:
|
|
618
|
+
|
|
619
|
+
```bash
|
|
620
|
+
# Clerk keys must start with specific prefixes
|
|
621
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxx # ✅ Correct
|
|
622
|
+
CLERK_SECRET_KEY=sk_test_xxx # ✅ Correct
|
|
623
|
+
|
|
624
|
+
# Database URL must be valid URL
|
|
625
|
+
DATABASE_URL=postgresql://user:pass@host:5432/db # ✅ Correct
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
**Issue: "Database connection failed"**
|
|
629
|
+
|
|
630
|
+
**Solution:** Verify DATABASE_URL is correct:
|
|
631
|
+
|
|
632
|
+
```bash
|
|
633
|
+
# Test connection
|
|
634
|
+
psql $DATABASE_URL
|
|
635
|
+
|
|
636
|
+
# Check for correct mode (Transaction vs Session)
|
|
637
|
+
# Transaction mode: port 6543, .pooler. domain
|
|
638
|
+
# Session mode: port 5432, direct domain
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
**Issue: "Clerk webhook verification failed"**
|
|
642
|
+
|
|
643
|
+
**Solution:** Verify webhook secret is correct:
|
|
644
|
+
|
|
645
|
+
```bash
|
|
646
|
+
# Check webhook secret matches Clerk dashboard
|
|
647
|
+
CLERK_WEBHOOK_SECRET=whsec_xxx # Must match exactly
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
## Related Documentation
|
|
653
|
+
|
|
654
|
+
- [Overview](./01-overview.md) - Framework introduction
|
|
655
|
+
- [Tech Stack](./02-techstack.md) - Technology breakdown
|
|
656
|
+
- [Clerk Authentication](./clerk-authentication.md) - Auth configuration
|
|
657
|
+
- [Supabase Integration](./supabase-integration.md) - Database configuration
|
|
658
|
+
- [Snowflake Integration](./snowflake-integration.md) - Data warehouse configuration
|