@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,559 @@
|
|
|
1
|
+
# DTT Framework - Implementation Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document explains how the DTT Framework was implemented, including key design decisions, architecture patterns, and code organization principles. Understanding these decisions will help you maintain and extend the framework.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## How the Framework Was Implemented
|
|
10
|
+
|
|
11
|
+
### Initial Setup
|
|
12
|
+
|
|
13
|
+
The framework was initialized using the T3 Stack template:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx create-t3-app@latest dtt-framework --typescript --tailwind --eslint --app --src-dir
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The T3 Stack provided:
|
|
20
|
+
- Next.js 15 with App Router
|
|
21
|
+
- TypeScript configuration
|
|
22
|
+
- Tailwind CSS
|
|
23
|
+
- ESLint
|
|
24
|
+
- Prettier
|
|
25
|
+
|
|
26
|
+
### Core Integrations Added
|
|
27
|
+
|
|
28
|
+
After initial setup, the following integrations were added:
|
|
29
|
+
|
|
30
|
+
1. **Clerk Authentication** - User management and auth
|
|
31
|
+
2. **Supabase** - Database, storage, and edge functions
|
|
32
|
+
3. **Drizzle ORM** - Type-safe database queries
|
|
33
|
+
4. **Hono** - API layer
|
|
34
|
+
5. **TanStack Query** - Server state management
|
|
35
|
+
6. **Zustand** - Client state management
|
|
36
|
+
7. **Snowflake SDK** - Data warehouse integration
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Key Design Decisions
|
|
41
|
+
|
|
42
|
+
### 1. Next.js App Router over Pages Router
|
|
43
|
+
|
|
44
|
+
**Decision:** Use App Router instead of Pages Router
|
|
45
|
+
|
|
46
|
+
**Rationale:**
|
|
47
|
+
- **React Server Components**: Better performance with server-side rendering
|
|
48
|
+
- **Streaming**: Progressive rendering for faster perceived performance
|
|
49
|
+
- **Nested Layouts**: Shared UI across routes
|
|
50
|
+
- **Route Groups**: Organize routes without affecting URL structure
|
|
51
|
+
- **Future-Proof**: App Router is the recommended approach
|
|
52
|
+
|
|
53
|
+
**Trade-offs:**
|
|
54
|
+
- Slightly steeper learning curve
|
|
55
|
+
- Some third-party libraries still catching up
|
|
56
|
+
|
|
57
|
+
### 2. Clerk over NextAuth.js
|
|
58
|
+
|
|
59
|
+
**Decision:** Use Clerk for authentication
|
|
60
|
+
|
|
61
|
+
**Rationale:**
|
|
62
|
+
- **Complete Solution**: Built-in UI components, no need to build auth screens
|
|
63
|
+
- **Organization Support**: Multi-tenant architecture out of the box
|
|
64
|
+
- **Webhooks**: Real-time user data synchronization
|
|
65
|
+
- **Developer Experience**: Less boilerplate code
|
|
66
|
+
- **Security**: SOC 2 Type II compliant
|
|
67
|
+
|
|
68
|
+
**Trade-offs:**
|
|
69
|
+
- Additional service dependency
|
|
70
|
+
- Cost for production use
|
|
71
|
+
|
|
72
|
+
### 3. Drizzle ORM over Prisma
|
|
73
|
+
|
|
74
|
+
**Decision:** Use Drizzle ORM for database access
|
|
75
|
+
|
|
76
|
+
**Rationale:**
|
|
77
|
+
- **Type Safety**: Full TypeScript support with inferred types
|
|
78
|
+
- **SQL-Like**: Queries resemble SQL, easy to learn
|
|
79
|
+
- **Lightweight**: Small bundle size, minimal overhead
|
|
80
|
+
- **Performance**: No query builder overhead, compiles to SQL
|
|
81
|
+
- **Migration System**: Built-in migration management
|
|
82
|
+
|
|
83
|
+
**Trade-offs:**
|
|
84
|
+
- Smaller ecosystem than Prisma
|
|
85
|
+
- Less mature tooling
|
|
86
|
+
|
|
87
|
+
### 4. Hono over tRPC
|
|
88
|
+
|
|
89
|
+
**Decision:** Use Hono for API layer instead of tRPC
|
|
90
|
+
|
|
91
|
+
**Rationale:**
|
|
92
|
+
- **Framework Agnostic**: Can be used outside Next.js
|
|
93
|
+
- **REST API**: Standard REST endpoints, easier to consume
|
|
94
|
+
- **Flexibility**: More control over request/response
|
|
95
|
+
- **Performance**: Smaller bundle size, faster execution
|
|
96
|
+
- **Middleware**: Composable middleware system
|
|
97
|
+
|
|
98
|
+
**Trade-offs:**
|
|
99
|
+
- No end-to-end type safety like tRPC
|
|
100
|
+
- Manual type definitions for API contracts
|
|
101
|
+
|
|
102
|
+
### 5. TanStack Query + Zustand over Redux
|
|
103
|
+
|
|
104
|
+
**Decision:** Use TanStack Query for server state and Zustand for client state
|
|
105
|
+
|
|
106
|
+
**Rationale:**
|
|
107
|
+
- **Separation of Concerns**: Clear distinction between server and client state
|
|
108
|
+
- **TanStack Query**: Specialized for server state with caching and synchronization
|
|
109
|
+
- **Zustand**: Lightweight, simple, no boilerplate
|
|
110
|
+
- **Better Performance**: No context re-renders with Zustand
|
|
111
|
+
- **Developer Experience**: Simpler mental model
|
|
112
|
+
|
|
113
|
+
**Trade-offs:**
|
|
114
|
+
- Two different state management systems to learn
|
|
115
|
+
- Need to decide where to put state
|
|
116
|
+
|
|
117
|
+
### 6. Supabase Transaction Mode over Session Mode
|
|
118
|
+
|
|
119
|
+
**Decision:** Use Transaction mode for database connection pooling
|
|
120
|
+
|
|
121
|
+
**Rationale:**
|
|
122
|
+
- **Serverless Optimization**: Designed for serverless environments
|
|
123
|
+
- **Connection Pooling**: Efficient connection reuse
|
|
124
|
+
- **Better Performance**: Faster connection times in serverless
|
|
125
|
+
- **Cost Effective**: Fewer active connections
|
|
126
|
+
|
|
127
|
+
**Trade-offs:**
|
|
128
|
+
- Requires `prepare: false` in postgres client
|
|
129
|
+
- Different connection URL format
|
|
130
|
+
|
|
131
|
+
### 7. Shadcn/ui over Component Libraries
|
|
132
|
+
|
|
133
|
+
**Decision:** Use Shadcn/ui for UI components
|
|
134
|
+
|
|
135
|
+
**Rationale:**
|
|
136
|
+
- **Copy-Paste**: Components are copied to codebase, full control
|
|
137
|
+
- **Radix UI Primitives**: Accessible, unstyled components
|
|
138
|
+
- **Tailwind Integration**: Styled with Tailwind CSS
|
|
139
|
+
- **Customizable**: Easy to modify to fit design
|
|
140
|
+
- **No Runtime Dependencies**: Lightweight, no library overhead
|
|
141
|
+
|
|
142
|
+
**Trade-offs:**
|
|
143
|
+
- More initial setup than pre-built component libraries
|
|
144
|
+
- Need to copy components individually
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Architecture Patterns Used
|
|
149
|
+
|
|
150
|
+
### 1. Feature-Based Organization
|
|
151
|
+
|
|
152
|
+
**Pattern:** Organize code by feature, not by file type
|
|
153
|
+
|
|
154
|
+
**Implementation:**
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
src/features/health-check/
|
|
158
|
+
├── components/
|
|
159
|
+
│ └── health-dashboard.tsx
|
|
160
|
+
├── config.ts
|
|
161
|
+
├── types.ts
|
|
162
|
+
└── index.ts
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Benefits:**
|
|
166
|
+
- **Co-location**: Related code is together
|
|
167
|
+
- **Easy Navigation**: Find all code for a feature in one place
|
|
168
|
+
- **Better Boundaries**: Clear feature boundaries
|
|
169
|
+
- **AI-Friendly**: Easier for AI to understand feature context
|
|
170
|
+
|
|
171
|
+
### 2. Route Groups
|
|
172
|
+
|
|
173
|
+
**Pattern:** Use Next.js route groups for logical organization
|
|
174
|
+
|
|
175
|
+
**Implementation:**
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
src/app/
|
|
179
|
+
├── (auth)/ # Auth routes group
|
|
180
|
+
│ ├── sign-in/
|
|
181
|
+
│ ├── sign-up/
|
|
182
|
+
│ └── layout.tsx
|
|
183
|
+
└── (dashboard)/ # Dashboard routes group
|
|
184
|
+
├── health/
|
|
185
|
+
├── page.tsx
|
|
186
|
+
└── layout.tsx
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Benefits:**
|
|
190
|
+
- **Shared Layouts**: Different layouts for different route groups
|
|
191
|
+
- **Clean URLs**: Group names don't affect URLs
|
|
192
|
+
- **Logical Organization**: Clear separation of concerns
|
|
193
|
+
|
|
194
|
+
### 3. API Route Aggregation
|
|
195
|
+
|
|
196
|
+
**Pattern:** Aggregate related routes under a common prefix
|
|
197
|
+
|
|
198
|
+
**Implementation:**
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// src/server/api/routes/health/index.ts
|
|
202
|
+
import { clerkHealthRoutes } from './clerk'
|
|
203
|
+
import { databaseHealthRoutes } from './database'
|
|
204
|
+
// ... other routes
|
|
205
|
+
|
|
206
|
+
export const healthRoutes = new Hono()
|
|
207
|
+
|
|
208
|
+
healthRoutes.route('/clerk', clerkHealthRoutes)
|
|
209
|
+
healthRoutes.route('/database', databaseHealthRoutes)
|
|
210
|
+
// ... other routes
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Benefits:**
|
|
214
|
+
- **Modular Routes**: Each service has its own route file
|
|
215
|
+
- **Clean Organization**: Easy to find and modify routes
|
|
216
|
+
- **Scalable**: Easy to add new services
|
|
217
|
+
|
|
218
|
+
### 4. Middleware Pipeline
|
|
219
|
+
|
|
220
|
+
**Pattern:** Use middleware for cross-cutting concerns
|
|
221
|
+
|
|
222
|
+
**Implementation:**
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
// src/server/api/index.ts
|
|
226
|
+
const app = new Hono().basePath('/api')
|
|
227
|
+
|
|
228
|
+
app.use('*', logger()) // Logging
|
|
229
|
+
app.use('*', cors()) // CORS
|
|
230
|
+
|
|
231
|
+
app.get('/ping', handler) // Public route
|
|
232
|
+
|
|
233
|
+
app.use('*', authMiddleware) // Auth protection
|
|
234
|
+
|
|
235
|
+
app.route('/health', healthRoutes)
|
|
236
|
+
app.route('/users', usersRoutes)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Benefits:**
|
|
240
|
+
- **Separation of Concerns**: Middleware handles cross-cutting logic
|
|
241
|
+
- **Reusability**: Middleware can be applied to multiple routes
|
|
242
|
+
- **Clean Handlers**: Route handlers focus on business logic
|
|
243
|
+
|
|
244
|
+
### 5. Type-Safe Environment Variables
|
|
245
|
+
|
|
246
|
+
**Pattern:** Use @t3-oss/env-nextjs for type-safe environment variables
|
|
247
|
+
|
|
248
|
+
**Implementation:**
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// src/config/env.ts
|
|
252
|
+
import { createEnv } from '@t3-oss/env-nextjs'
|
|
253
|
+
import { z } from 'zod'
|
|
254
|
+
|
|
255
|
+
export const env = createEnv({
|
|
256
|
+
server: {
|
|
257
|
+
DATABASE_URL: z.string().url(),
|
|
258
|
+
CLERK_SECRET_KEY: z.string().startsWith('sk_'),
|
|
259
|
+
},
|
|
260
|
+
client: {
|
|
261
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().startsWith('pk_'),
|
|
262
|
+
},
|
|
263
|
+
runtimeEnv: {
|
|
264
|
+
DATABASE_URL: process.env.DATABASE_URL,
|
|
265
|
+
CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
|
|
266
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
|
|
267
|
+
},
|
|
268
|
+
})
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Benefits:**
|
|
272
|
+
- **Type Safety**: Catch missing variables at build time
|
|
273
|
+
- **Validation**: Ensure variables are correctly formatted
|
|
274
|
+
- **Auto-Completion**: IDE suggestions for environment variables
|
|
275
|
+
- **Clear Errors**: Helpful error messages for missing variables
|
|
276
|
+
|
|
277
|
+
### 6. Custom Hooks Pattern
|
|
278
|
+
|
|
279
|
+
**Pattern:** Create custom hooks for reusable logic
|
|
280
|
+
|
|
281
|
+
**Implementation:**
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
// src/hooks/queries/use-health-checks.ts
|
|
285
|
+
'use client'
|
|
286
|
+
|
|
287
|
+
import { useQuery } from '@tanstack/react-query'
|
|
288
|
+
|
|
289
|
+
export function useHealthChecks() {
|
|
290
|
+
return useQuery({
|
|
291
|
+
queryKey: ['health-checks'],
|
|
292
|
+
queryFn: async () => {
|
|
293
|
+
const response = await fetch('/api/health/all')
|
|
294
|
+
if (!response.ok) throw new Error('Failed to fetch health checks')
|
|
295
|
+
return response.json()
|
|
296
|
+
},
|
|
297
|
+
})
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**Benefits:**
|
|
302
|
+
- **Reusability**: Logic can be reused across components
|
|
303
|
+
- **Testability**: Hooks can be tested independently
|
|
304
|
+
- **Separation of Concerns**: Data fetching logic separated from UI
|
|
305
|
+
- **Cleaner Components**: Components focus on rendering
|
|
306
|
+
|
|
307
|
+
### 7. Webhook Synchronization
|
|
308
|
+
|
|
309
|
+
**Pattern:** Use webhooks to sync data between services
|
|
310
|
+
|
|
311
|
+
**Implementation:**
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
// src/app/api/webhooks/clerk/route.ts
|
|
315
|
+
export async function POST(req: Request) {
|
|
316
|
+
// Verify webhook signature
|
|
317
|
+
const wh = new Webhook(env.CLERK_WEBHOOK_SECRET)
|
|
318
|
+
const event = wh.verify(body, headers) as WebhookEvent
|
|
319
|
+
|
|
320
|
+
// Handle events
|
|
321
|
+
if (event.type === 'user.created') {
|
|
322
|
+
await db.insert(users).values(event.data)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return new Response(JSON.stringify({ received: true }), { status: 200 })
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Benefits:**
|
|
330
|
+
- **Real-time Sync**: Data is synced immediately
|
|
331
|
+
- **Decoupled**: Services don't need to know about each other
|
|
332
|
+
- **Reliable**: Webhooks are retried on failure
|
|
333
|
+
- **Audit Trail**: Webhook events provide audit trail
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Code Organization Principles
|
|
338
|
+
|
|
339
|
+
### 1. Separation of Concerns
|
|
340
|
+
|
|
341
|
+
Each module has a single responsibility:
|
|
342
|
+
|
|
343
|
+
- **Components**: Handle rendering and user interaction
|
|
344
|
+
- **Hooks**: Handle data fetching and state management
|
|
345
|
+
- **API Routes**: Handle HTTP requests and responses
|
|
346
|
+
- **Database Queries**: Handle database operations
|
|
347
|
+
- **Utilities**: Handle pure functions and helpers
|
|
348
|
+
|
|
349
|
+
### 2. Explicit Imports
|
|
350
|
+
|
|
351
|
+
Use explicit imports for better tree-shaking:
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
// ✅ Good - Explicit import
|
|
355
|
+
import { Button } from '@/components/ui/button'
|
|
356
|
+
|
|
357
|
+
// ❌ Bad - Barrel import
|
|
358
|
+
import * as UI from '@/components/ui'
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### 3. Path Aliases
|
|
362
|
+
|
|
363
|
+
Use path aliases for clean imports:
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
// tsconfig.json
|
|
367
|
+
{
|
|
368
|
+
"compilerOptions": {
|
|
369
|
+
"paths": {
|
|
370
|
+
"@/*": ["./src/*"]
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### 4. TypeScript Strict Mode
|
|
377
|
+
|
|
378
|
+
Always use TypeScript in strict mode:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// tsconfig.json
|
|
382
|
+
{
|
|
383
|
+
"compilerOptions": {
|
|
384
|
+
"strict": true,
|
|
385
|
+
"noUncheckedIndexedAccess": true,
|
|
386
|
+
"noImplicitReturns": true,
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### 5. Consistent Naming
|
|
392
|
+
|
|
393
|
+
Follow consistent naming conventions:
|
|
394
|
+
|
|
395
|
+
- **Components**: PascalCase (`UserProfile.tsx`)
|
|
396
|
+
- **Hooks**: camelCase with `use` prefix (`useUserProfile.ts`)
|
|
397
|
+
- **Utilities**: camelCase (`formatDate.ts`)
|
|
398
|
+
- **Types**: PascalCase (`UserProfile.ts`)
|
|
399
|
+
- **Constants**: UPPER_SNAKE_CASE (`API_BASE_URL`)
|
|
400
|
+
|
|
401
|
+
### 6. File Naming
|
|
402
|
+
|
|
403
|
+
Use clear, descriptive file names:
|
|
404
|
+
|
|
405
|
+
```
|
|
406
|
+
src/features/health-check/
|
|
407
|
+
├── components/health-dashboard.tsx # Component
|
|
408
|
+
├── config.ts # Configuration
|
|
409
|
+
├── types.ts # Type definitions
|
|
410
|
+
└── index.ts # Public exports
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
## File Structure Decisions
|
|
416
|
+
|
|
417
|
+
### Why This Structure?
|
|
418
|
+
|
|
419
|
+
```
|
|
420
|
+
src/
|
|
421
|
+
├── app/ # Next.js App Router
|
|
422
|
+
├── components/ # React components
|
|
423
|
+
├── features/ # Feature modules
|
|
424
|
+
├── hooks/ # React hooks
|
|
425
|
+
├── lib/ # Utilities and clients
|
|
426
|
+
├── server/ # Server-side code
|
|
427
|
+
├── stores/ # Zustand stores
|
|
428
|
+
├── types/ # TypeScript types
|
|
429
|
+
└── config/ # Configuration
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**Rationale:**
|
|
433
|
+
- **Framework Conventions**: Follows Next.js and React conventions
|
|
434
|
+
- **Clear Separation**: Client and server code are separate
|
|
435
|
+
- **Feature-Based**: Features are self-contained
|
|
436
|
+
- **Scalable**: Easy to add new features
|
|
437
|
+
|
|
438
|
+
### Server-Side Code Organization
|
|
439
|
+
|
|
440
|
+
```
|
|
441
|
+
src/server/
|
|
442
|
+
├── api/ # API layer
|
|
443
|
+
│ ├── index.ts # Hono app instance
|
|
444
|
+
│ ├── middleware/ # API middleware
|
|
445
|
+
│ └── routes/ # API routes
|
|
446
|
+
└── db/ # Database layer
|
|
447
|
+
├── index.ts # Drizzle client
|
|
448
|
+
├── schema/ # Database schemas
|
|
449
|
+
├── queries/ # Database queries
|
|
450
|
+
└── migrations/ # Migration files
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**Rationale:**
|
|
454
|
+
- **API vs DB**: API routes and database queries are separate
|
|
455
|
+
- **Modular**: Each module is self-contained
|
|
456
|
+
- **Testable**: Each module can be tested independently
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## Performance Considerations
|
|
461
|
+
|
|
462
|
+
### 1. Connection Pooling
|
|
463
|
+
|
|
464
|
+
Using Supabase Transaction mode for efficient connection reuse:
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
const conn = globalForDb.conn ?? postgres(env.DATABASE_URL, { prepare: false })
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### 2. Response Time Tracking
|
|
471
|
+
|
|
472
|
+
All health check endpoints track response time:
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
const start = performance.now()
|
|
476
|
+
// ... perform check
|
|
477
|
+
return c.json({
|
|
478
|
+
responseTimeMs: Math.round(performance.now() - start),
|
|
479
|
+
})
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### 3. TanStack Query Caching
|
|
483
|
+
|
|
484
|
+
Configuring stale time to reduce unnecessary requests:
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
new QueryClient({
|
|
488
|
+
defaultOptions: {
|
|
489
|
+
queries: {
|
|
490
|
+
staleTime: 60 * 1000, // 60 seconds
|
|
491
|
+
retry: 1
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
})
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### 4. React Server Components
|
|
498
|
+
|
|
499
|
+
Using Server Components to reduce client-side JavaScript:
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
// Server Component (default)
|
|
503
|
+
export default async function ServerComponent() {
|
|
504
|
+
const data = await fetchData()
|
|
505
|
+
return <div>{data}</div>
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
## Security Considerations
|
|
512
|
+
|
|
513
|
+
### 1. Environment Variables
|
|
514
|
+
|
|
515
|
+
All sensitive data in environment variables:
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
// ✅ Good - Environment variable
|
|
519
|
+
const apiKey = env.API_KEY
|
|
520
|
+
|
|
521
|
+
// ❌ Bad - Hardcoded
|
|
522
|
+
const apiKey = 'sk_test_xxx'
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### 2. Webhook Verification
|
|
526
|
+
|
|
527
|
+
Verifying webhook signatures to prevent spoofing:
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
const wh = new Webhook(env.CLERK_WEBHOOK_SECRET)
|
|
531
|
+
const event = wh.verify(body, headers)
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### 3. Auth Middleware
|
|
535
|
+
|
|
536
|
+
Protecting all API routes with authentication:
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
app.use('*', authMiddleware)
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### 4. Service Role Key
|
|
543
|
+
|
|
544
|
+
Using service role key for server-side operations:
|
|
545
|
+
|
|
546
|
+
```typescript
|
|
547
|
+
// Server-side - bypasses RLS
|
|
548
|
+
const supabaseAdmin = createClient(url, serviceRoleKey)
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## Related Documentation
|
|
554
|
+
|
|
555
|
+
- [Overview](./01-overview.md) - Framework introduction
|
|
556
|
+
- [Tech Stack](./02-techstack.md) - Technology choices
|
|
557
|
+
- [API Layer](./api-layer.md) - API implementation
|
|
558
|
+
- [State Management](./state-management.md) - State patterns
|
|
559
|
+
- [What Did I Miss](./what-did-i-miss.md) - Potential improvements
|