@kood/claude-code 0.1.5 → 0.1.7

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 (77) hide show
  1. package/dist/index.js +21 -243
  2. package/package.json +1 -1
  3. package/templates/hono/CLAUDE.md +10 -6
  4. package/templates/hono/docs/deployment/index.md +5 -0
  5. package/templates/hono/docs/library/hono/index.md +6 -0
  6. package/templates/hono/docs/library/prisma/index.md +3 -0
  7. package/templates/npx/CLAUDE.md +8 -2
  8. package/templates/tanstack-start/CLAUDE.md +105 -259
  9. package/templates/tanstack-start/docs/deployment/cloudflare.md +37 -424
  10. package/templates/tanstack-start/docs/deployment/index.md +57 -286
  11. package/templates/tanstack-start/docs/deployment/nitro.md +36 -318
  12. package/templates/tanstack-start/docs/deployment/railway.md +40 -409
  13. package/templates/tanstack-start/docs/deployment/vercel.md +43 -465
  14. package/templates/tanstack-start/docs/design/accessibility.md +56 -326
  15. package/templates/tanstack-start/docs/design/color.md +37 -179
  16. package/templates/tanstack-start/docs/design/components.md +77 -311
  17. package/templates/tanstack-start/docs/design/index.md +24 -87
  18. package/templates/tanstack-start/docs/design/safe-area.md +51 -250
  19. package/templates/tanstack-start/docs/design/spacing.md +57 -276
  20. package/templates/tanstack-start/docs/design/tailwind-setup.md +45 -359
  21. package/templates/tanstack-start/docs/design/typography.md +40 -284
  22. package/templates/tanstack-start/docs/guides/best-practices.md +3 -8
  23. package/templates/tanstack-start/docs/guides/env-setup.md +3 -3
  24. package/templates/tanstack-start/docs/library/better-auth/2fa.md +27 -115
  25. package/templates/tanstack-start/docs/library/better-auth/advanced.md +22 -105
  26. package/templates/tanstack-start/docs/library/better-auth/index.md +17 -66
  27. package/templates/tanstack-start/docs/library/better-auth/plugins.md +11 -88
  28. package/templates/tanstack-start/docs/library/better-auth/session.md +12 -92
  29. package/templates/tanstack-start/docs/library/better-auth/setup.md +9 -91
  30. package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +30 -358
  31. package/templates/tanstack-start/docs/library/prisma/config.md +27 -327
  32. package/templates/tanstack-start/docs/library/prisma/crud.md +46 -174
  33. package/templates/tanstack-start/docs/library/prisma/index.md +23 -113
  34. package/templates/tanstack-start/docs/library/prisma/relations.md +31 -153
  35. package/templates/tanstack-start/docs/library/prisma/schema.md +40 -217
  36. package/templates/tanstack-start/docs/library/prisma/setup.md +13 -113
  37. package/templates/tanstack-start/docs/library/prisma/transactions.md +20 -110
  38. package/templates/tanstack-start/docs/library/tanstack-query/index.md +12 -99
  39. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +28 -107
  40. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +44 -146
  41. package/templates/tanstack-start/docs/library/tanstack-query/setup.md +11 -73
  42. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +33 -127
  43. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +49 -149
  44. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +19 -112
  45. package/templates/tanstack-start/docs/library/tanstack-start/index.md +33 -80
  46. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +28 -106
  47. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +21 -118
  48. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +41 -172
  49. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +6 -39
  50. package/templates/tanstack-start/docs/library/zod/basic-types.md +33 -145
  51. package/templates/tanstack-start/docs/library/zod/complex-types.md +32 -156
  52. package/templates/tanstack-start/docs/library/zod/index.md +22 -150
  53. package/templates/tanstack-start/docs/library/zod/transforms.md +20 -129
  54. package/templates/tanstack-start/docs/library/zod/validation.md +39 -155
  55. package/templates/hono/docs/commands/git.md +0 -145
  56. package/templates/hono/docs/mcp/context7.md +0 -106
  57. package/templates/hono/docs/mcp/index.md +0 -176
  58. package/templates/hono/docs/mcp/sequential-thinking.md +0 -101
  59. package/templates/hono/docs/mcp/serena.md +0 -269
  60. package/templates/hono/docs/mcp/sgrep.md +0 -105
  61. package/templates/hono/docs/skills/gemini-review/SKILL.md +0 -220
  62. package/templates/hono/docs/skills/gemini-review/references/checklists.md +0 -136
  63. package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +0 -303
  64. package/templates/npx/docs/commands/git.md +0 -145
  65. package/templates/npx/docs/mcp/index.md +0 -60
  66. package/templates/npx/docs/skills/gemini-review/SKILL.md +0 -220
  67. package/templates/npx/docs/skills/gemini-review/references/checklists.md +0 -134
  68. package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +0 -301
  69. package/templates/tanstack-start/docs/commands/git.md +0 -145
  70. package/templates/tanstack-start/docs/mcp/context7.md +0 -204
  71. package/templates/tanstack-start/docs/mcp/index.md +0 -177
  72. package/templates/tanstack-start/docs/mcp/sequential-thinking.md +0 -180
  73. package/templates/tanstack-start/docs/mcp/serena.md +0 -269
  74. package/templates/tanstack-start/docs/mcp/sgrep.md +0 -174
  75. package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +0 -220
  76. package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +0 -144
  77. package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +0 -292
@@ -1,324 +1,80 @@
1
1
  # 타이포그래피
2
2
 
3
- > **상위 문서**: [UI/UX 디자인 가이드](./index.md)
4
-
5
- 타이포그래피(Typography)는 텍스트를 읽기 쉽고 시각적으로 매력적으로 만드는 기술입니다.
6
-
7
3
  ## 기본 원칙
4
+ - 폰트 2-3개만 (제목용, 본문용, 코드용)
5
+ - 크기로 계층 표현
6
+ - 일관된 스타일
8
7
 
9
- ### 1. 폰트는 2-3개만
10
-
11
- > 폰트가 많을수록 디자인은 산만해집니다.
12
-
13
- ```
14
- 권장 구성:
15
- - 제목용 폰트 1개
16
- - 본문용 폰트 1개
17
- - (선택) 코드용 폰트 1개
18
- ```
19
-
20
- ### 2. 크기로 계층 표현
21
-
22
- > 제목과 본문의 크기 차이로 중요도를 표현합니다.
23
-
24
- ```
25
- h1 (제목) ━━━━━━━━━━━━━━━━━━━━━━━ 가장 큼
26
- h2 (부제목) ━━━━━━━━━━━━━━━━━
27
- h3 (소제목) ━━━━━━━━━━━━
28
- p (본문) ━━━━━━━━ 기준 크기
29
- small ━━━━━━ 가장 작음
30
- ```
31
-
32
- ### 3. 일관된 스타일
33
-
34
- > 같은 역할의 텍스트는 항상 같은 스타일을 사용합니다.
35
-
36
- ## 폰트 선택 가이드
37
-
38
- ### Sans-serif (산세리프) - 본문에 권장
39
-
40
- 획의 끝에 장식이 없는 깔끔한 폰트입니다.
41
-
42
- | 폰트 | 특징 | 추천 용도 |
43
- |------|------|----------|
44
- | **Inter** | 현대적, 가독성 뛰어남 | 웹 전반 |
45
- | **Pretendard** | 한글 최적화, Inter 호환 | 한글 프로젝트 |
46
- | **Noto Sans KR** | 한글/영문 균형 | 다국어 프로젝트 |
47
- | **Roboto** | Google 스타일 | Material Design |
48
- | **SF Pro** | Apple 스타일 | iOS/macOS 앱 |
49
-
50
- ### Serif (세리프) - 제목에 선택적
51
-
52
- 획의 끝에 장식(세리프)이 있는 전통적인 폰트입니다.
53
-
54
- | 폰트 | 특징 | 추천 용도 |
55
- |------|------|----------|
56
- | **Georgia** | 클래식, 신뢰감 | 블로그, 뉴스 |
57
- | **Merriweather** | 가독성 높음 | 긴 글 읽기 |
58
- | **Noto Serif KR** | 한글 세리프 | 격식있는 제목 |
59
-
60
- ### Monospace (고정폭) - 코드용
8
+ ## 폰트 선택
61
9
 
62
- 모든 글자가 같은 너비를 가지는 폰트입니다.
63
-
64
- | 폰트 | 특징 |
10
+ | 폰트 | 용도 |
65
11
  |------|------|
66
- | **JetBrains Mono** | 개발자용, 리가처 지원 |
67
- | **Fira Code** | 리가처 지원 |
68
- | **SF Mono** | Apple 스타일 |
69
-
70
- ## 폰트 크기 시스템
12
+ | Pretendard | 한글 프로젝트 (권장) |
13
+ | Inter | 영문, 전반 |
14
+ | Noto Sans KR | 다국어 프로젝트 |
15
+ | JetBrains Mono | 코드 |
71
16
 
72
- ### 기본 크기 체계
17
+ ## 크기 시스템
73
18
 
74
19
  ```css
75
- /* Tailwind 기본 크기 */
76
- text-xs 0.75rem 12px 작은 레이블, 캡션
77
- text-sm 0.875rem 14px 보조 텍스트, 메타 정보
78
- text-base 1rem 16px 본문 (기본)
79
- text-lg 1.125rem 18px 강조 본문
80
- text-xl 1.25rem 20px 소제목 (h4)
81
- text-2xl 1.5rem 24px 섹션 제목 (h3)
82
- text-3xl 1.875rem 30px 페이지 부제목 (h2)
83
- text-4xl 2.25rem 36px 페이지 제목 (h1)
84
- text-5xl 3rem 48px 히어로 제목
20
+ text-xs 12px 작은 레이블
21
+ text-sm 14px 보조 텍스트
22
+ text-base 16px 본문 (기본)
23
+ text-lg 18px 강조 본문
24
+ text-xl 20px 소제목 (h4)
25
+ text-2xl 24px 섹션 제목 (h3)
26
+ text-3xl 30px 부제목 (h2)
27
+ text-4xl 36px 페이지 제목 (h1)
28
+ text-5xl 48px 히어로
85
29
  ```
86
30
 
87
- ### 실제 적용 예시
88
-
89
31
  ```tsx
90
- // 페이지 제목
91
- <h1 className="text-4xl font-bold">대시보드</h1>
92
-
93
- // 섹션 제목
94
- <h2 className="text-2xl font-semibold">최근 활동</h2>
95
-
96
- // 카드 제목
97
- <h3 className="text-xl font-medium">사용자 통계</h3>
98
-
99
- // 본문
100
- <p className="text-base">오늘 방문자 수는 1,234명입니다.</p>
101
-
102
- // 보조 텍스트
103
- <span className="text-sm text-gray-500">5분 전 업데이트</span>
32
+ <h1 className="text-4xl font-bold">제목</h1>
33
+ <h2 className="text-2xl font-semibold">섹션</h2>
34
+ <p className="text-base">본문</p>
35
+ <span className="text-sm text-gray-500">보조</span>
104
36
  ```
105
37
 
106
38
  ## 줄 간격 (Line Height)
107
39
 
108
- ### 왜 중요한가?
109
-
110
- 줄 간격이 좁으면 답답하고, 너무 넓으면 텍스트가 흩어져 보입니다.
111
-
112
- ```
113
- 줄 간격 너무 좁음 (1.2) 적절한 줄 간격 (1.5)
114
- ━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━
115
- 이 텍스트는 줄 간격이 이 텍스트는 줄 간격이
116
- 너무 좁아서 읽기가 적절해서 읽기가
117
- 불편합니다. 편합니다.
118
- ━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━
119
- ```
120
-
121
- ### Tailwind 줄 간격
122
-
123
40
  ```css
124
- leading-none 1 제목 (한 줄)
125
- leading-tight 1.25 짧은 제목
126
- leading-snug 1.375 부제목
127
- leading-normal 1.5 본문 (기본, 권장)
41
+ leading-tight 1.25 제목
42
+ leading-normal 1.5 본문 (권장)
128
43
  leading-relaxed 1.625 긴 글
129
- leading-loose 2 매우 여유로운 글
130
- ```
131
-
132
- ### 텍스트 길이별 권장 줄 간격
133
-
134
- ```tsx
135
- // 짧은 제목 - 타이트하게
136
- <h1 className="text-4xl leading-tight">한 줄 제목</h1>
137
-
138
- // 긴 본문 - 여유롭게
139
- <p className="text-base leading-relaxed">
140
- 긴 본문 텍스트는 줄 간격이 넉넉해야
141
- 읽기가 편합니다.
142
- </p>
143
44
  ```
144
45
 
145
- ## 글자 굵기 (Font Weight)
146
-
147
- ### Tailwind 굵기 옵션
46
+ ## 굵기 (Font Weight)
148
47
 
149
48
  ```css
150
- font-thin 100 거의 사용 안함
151
- font-extralight 200 거의 사용 안함
152
- font-light 300 밝은 테마 대형 제목
153
- font-normal 400 본문 (기본)
154
- font-medium 500 약간 강조
155
- font-semibold 600 부제목, 버튼
156
- font-bold 700 제목, 강조
157
- font-extrabold 800 히어로 제목
158
- font-black 900 임팩트 제목
159
- ```
160
-
161
- ### 계층별 권장 굵기
162
-
163
- ```tsx
164
- // 메인 제목 - 볼드
165
- <h1 className="text-4xl font-bold">제목</h1>
166
-
167
- // 부제목 - 세미볼드
168
- <h2 className="text-2xl font-semibold">부제목</h2>
169
-
170
- // 본문 - 일반
171
- <p className="text-base font-normal">본문 텍스트</p>
172
-
173
- // 강조 - 미디엄
174
- <strong className="font-medium">중요한 내용</strong>
49
+ font-normal 400 본문
50
+ font-medium 500 약간 강조
51
+ font-semibold 600 부제목, 버튼
52
+ font-bold 700 제목
175
53
  ```
176
54
 
177
55
  ## 가독성 최적화
178
56
 
179
- ### 줄 길이 (Line Length)
180
-
181
- > 한 줄에 너무 많은 글자는 읽기 어렵습니다.
182
-
183
- ```
184
- 권장: 45-75자 (영문 기준)
185
- 한글: 25-35자
186
-
187
- Tailwind로 제한:
188
- max-w-prose → 65ch (약 65자)
189
- max-w-xl → 36rem
190
- max-w-2xl → 42rem
191
- ```
192
-
193
57
  ```tsx
194
- // 본문 컨테이너
58
+ // 길이 제한 (45-75자)
195
59
  <article className="max-w-prose mx-auto">
196
- <p>이 텍스트는 적절한 줄 길이로 제한되어 읽기 편합니다.</p>
197
- </article>
198
- ```
199
-
200
- ### 글자 간격 (Letter Spacing)
201
-
202
- ```css
203
- tracking-tighter -0.05em 대형 제목
204
- tracking-tight -0.025em 제목
205
- tracking-normal 0 본문 (기본)
206
- tracking-wide 0.025em 대문자, 작은 텍스트
207
- tracking-wider 0.05em 레이블
208
- tracking-widest 0.1em 버튼 텍스트
209
- ```
210
60
 
211
- ```tsx
212
- // 대형 제목 - 약간 좁게
213
- <h1 className="text-5xl tracking-tight">히어로 제목</h1>
214
-
215
- // 작은 레이블 - 약간 넓게
216
- <span className="text-xs tracking-wide uppercase">NEW</span>
61
+ // 글자 간격
62
+ <h1 className="text-5xl tracking-tight">히어로</h1>
63
+ <span className="text-xs tracking-wide uppercase">LABEL</span>
217
64
  ```
218
65
 
219
- ## 실전 타이포그래피 시스템
220
-
221
- ### 완성된 텍스트 스타일 세트
222
-
223
- ```tsx
224
- // src/components/ui/typography.tsx
225
-
226
- // 페이지 제목
227
- export const PageTitle = ({ children }) => (
228
- <h1 className="text-4xl font-bold tracking-tight text-gray-900 dark:text-white">
229
- {children}
230
- </h1>
231
- )
232
-
233
- // 섹션 제목
234
- export const SectionTitle = ({ children }) => (
235
- <h2 className="text-2xl font-semibold text-gray-900 dark:text-white">
236
- {children}
237
- </h2>
238
- )
239
-
240
- // 카드 제목
241
- export const CardTitle = ({ children }) => (
242
- <h3 className="text-lg font-medium text-gray-900 dark:text-white">
243
- {children}
244
- </h3>
245
- )
246
-
247
- // 본문
248
- export const Body = ({ children }) => (
249
- <p className="text-base leading-relaxed text-gray-700 dark:text-gray-300">
250
- {children}
251
- </p>
252
- )
253
-
254
- // 보조 텍스트
255
- export const Caption = ({ children }) => (
256
- <span className="text-sm text-gray-500 dark:text-gray-400">
257
- {children}
258
- </span>
259
- )
260
-
261
- // 레이블
262
- export const Label = ({ children }) => (
263
- <span className="text-xs font-medium uppercase tracking-wide text-gray-500">
264
- {children}
265
- </span>
266
- )
267
- ```
268
-
269
- ## 폰트 설정
270
-
271
- ### Tailwind CSS v4 폰트 설정
66
+ ## Tailwind 폰트 설정
272
67
 
273
68
  ```css
274
- /* src/styles/app.css */
275
- @import "tailwindcss";
276
-
277
69
  @theme {
278
- /* 폰트 패밀리 */
279
70
  --font-sans: "Pretendard", "Inter", system-ui, sans-serif;
280
- --font-mono: "JetBrains Mono", "Fira Code", monospace;
71
+ --font-mono: "JetBrains Mono", monospace;
281
72
  }
282
73
  ```
283
74
 
284
- ### Next.js / TanStack Start 폰트 로딩
285
-
286
- ```tsx
287
- // Google Fonts 사용 시
288
- // src/routes/__root.tsx
289
- import { Link } from '@tanstack/react-router'
290
-
291
- export const Route = createRootRoute({
292
- component: () => (
293
- <html>
294
- <head>
295
- <link rel="preconnect" href="https://fonts.googleapis.com" />
296
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
297
- <link
298
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
299
- rel="stylesheet"
300
- />
301
- </head>
302
- <body className="font-sans">
303
- <Outlet />
304
- </body>
305
- </html>
306
- ),
307
- })
308
- ```
309
-
310
75
  ## 체크리스트
311
76
 
312
- ### 반드시 지켜야
313
-
314
- - [ ] 폰트 종류 2-3개 이하
315
- - [ ] 본문 크기 16px 이상
316
- - [ ] 본문 줄 간격 1.5 이상
317
- - [ ] 제목과 본문의 명확한 크기 차이
318
-
319
- ### 권장 사항
320
-
321
- - [ ] 한글 최적화 폰트 사용 (Pretendard, Noto Sans KR)
322
- - [ ] 텍스트 컨테이너 최대 너비 제한
323
- - [ ] 일관된 텍스트 스타일 컴포넌트 사용
324
- - [ ] 다크 모드 텍스트 색상 대응
77
+ - [ ] 폰트 2-3개 이하
78
+ - [ ] 본문 16px 이상
79
+ - [ ] 간격 1.5 이상
80
+ - [ ] 제목/본문 명확한 크기 차이
@@ -304,7 +304,6 @@ const UsersPage = (): JSX.Element => {
304
304
  import { useState, useMemo, useEffect, useCallback } from 'react'
305
305
  import { useParams, useNavigate } from '@tanstack/react-router'
306
306
  import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
307
- import { useServerFn } from '@tanstack/react-start'
308
307
  import { useAuthStore } from '@/stores/auth'
309
308
  import { getUsers, createUser, deleteUser } from '@/services/user'
310
309
  import type { User } from '@/types'
@@ -339,24 +338,20 @@ export const useUsers = (): UseUsersReturn => {
339
338
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
340
339
  // 3. React Query (useQuery → useMutation)
341
340
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
342
- const getUsersFn = useServerFn(getUsers)
343
- const createUserFn = useServerFn(createUser)
344
- const deleteUserFn = useServerFn(deleteUser)
345
-
346
341
  const { data: users, isLoading, error } = useQuery({
347
342
  queryKey: ['users'],
348
- queryFn: () => getUsersFn(),
343
+ queryFn: () => getUsers(),
349
344
  })
350
345
 
351
346
  const createMutation = useMutation({
352
- mutationFn: createUserFn,
347
+ mutationFn: createUser,
353
348
  onSuccess: () => {
354
349
  queryClient.invalidateQueries({ queryKey: ['users'] })
355
350
  },
356
351
  })
357
352
 
358
353
  const deleteMutation = useMutation({
359
- mutationFn: deleteUserFn,
354
+ mutationFn: deleteUser,
360
355
  onSuccess: () => {
361
356
  queryClient.invalidateQueries({ queryKey: ['users'] })
362
357
  },
@@ -226,7 +226,7 @@ export const clientEnv = parseClientEnv()
226
226
  ```typescript
227
227
  // app/server-functions/users.ts
228
228
  import { createServerFn } from '@tanstack/react-start'
229
- import { getServerEnv } from '~/config/env'
229
+ import { getServerEnv } from '@/config/env'
230
230
 
231
231
  export const getUsers = createServerFn({ method: 'GET' })
232
232
  .handler(async () => {
@@ -248,7 +248,7 @@ export const getUsers = createServerFn({ method: 'GET' })
248
248
 
249
249
  ```tsx
250
250
  // app/components/AppHeader.tsx
251
- import { clientEnv } from '~/config/env'
251
+ import { clientEnv } from '@/config/env'
252
252
 
253
253
  export const AppHeader = () => {
254
254
  return (
@@ -282,7 +282,7 @@ const appName = import.meta.env.VITE_APP_NAME // ✅ VITE_ 접두사만
282
282
 
283
283
  ```typescript
284
284
  // app/lib/auth.ts
285
- import { getServerEnv } from '~/config/env'
285
+ import { getServerEnv } from '@/config/env'
286
286
 
287
287
  export const getAuthConfig = () => {
288
288
  const env = getServerEnv()
@@ -1,136 +1,48 @@
1
1
  # Better Auth - 2단계 인증 (2FA)
2
2
 
3
- > **상위 문서**: [Better Auth](./index.md)
4
-
5
- ## 서버 설정
3
+ ## 서버
6
4
 
7
5
  ```typescript
8
- import { betterAuth } from 'better-auth'
9
6
  import { twoFactor } from 'better-auth/plugins'
10
7
 
11
- export const auth = betterAuth({
12
- plugins: [
13
- twoFactor({
14
- issuer: 'My Application',
15
- otpOptions: {
16
- async sendOTP({ user, otp }) {
17
- await sendEmail({
18
- to: user.email,
19
- subject: 'Your verification code',
20
- html: `Your code is: ${otp}`,
21
- })
22
- },
23
- period: 300, // 5분
24
- length: 6,
25
- },
26
- backupCodeLength: 10,
27
- backupCodeCount: 10,
28
- }),
29
- ],
30
- })
8
+ plugins: [
9
+ twoFactor({
10
+ issuer: 'My App',
11
+ otpOptions: {
12
+ async sendOTP({ user, otp }) { await sendEmail({ to: user.email, html: `Code: ${otp}` }) },
13
+ period: 300, length: 6,
14
+ },
15
+ backupCodeLength: 10,
16
+ backupCodeCount: 10,
17
+ }),
18
+ ]
31
19
  ```
32
20
 
33
- ## 클라이언트 설정
21
+ ## 클라이언트
34
22
 
35
23
  ```typescript
36
24
  import { twoFactorClient } from 'better-auth/client/plugins'
37
-
38
- const authClient = createAuthClient({
39
- plugins: [
40
- twoFactorClient({
41
- twoFactorPage: '/two-factor',
42
- }),
43
- ],
44
- })
25
+ plugins: [twoFactorClient({ twoFactorPage: '/two-factor' })]
45
26
  ```
46
27
 
47
- ## 2FA 활성화
28
+ ## 사용법
48
29
 
49
30
  ```typescript
50
- // 2FA 활성화
51
- const { data } = await authClient.twoFactor.enable({
52
- password: 'userPassword123',
53
- })
54
- console.log('TOTP URI:', data.totpURI)
55
- console.log('Backup codes:', data.backupCodes)
56
- ```
31
+ // 활성화
32
+ const { data } = await authClient.twoFactor.enable({ password })
33
+ // data.totpURI, data.backupCodes
57
34
 
58
- ## TOTP 코드 검증
59
-
60
- ```typescript
61
- // TOTP 코드 검증
62
- await authClient.twoFactor.verifyTotp({
63
- code: '123456',
64
- })
65
- ```
35
+ // TOTP 검증
36
+ await authClient.twoFactor.verifyTotp({ code: '123456' })
66
37
 
67
- ## OTP 전송 및 검증
68
-
69
- ```typescript
70
- // OTP 전송
38
+ // OTP 전송 및 검증
71
39
  await authClient.twoFactor.sendOtp()
40
+ await authClient.twoFactor.verifyOtp({ code })
72
41
 
73
- // OTP 검증
74
- await authClient.twoFactor.verifyOtp({
75
- code: '123456',
76
- })
77
- ```
78
-
79
- ## 백업 코드
80
-
81
- ```typescript
82
- // 백업 코드 사용
83
- await authClient.twoFactor.useBackupCode({
84
- code: 'ABCD-1234-EFGH',
85
- })
86
-
87
- // 백업 코드 재생성
88
- const { data: newCodes } = await authClient.twoFactor.regenerateBackupCodes({
89
- password: 'userPassword123',
90
- })
91
- ```
92
-
93
- ## 2FA 비활성화
94
-
95
- ```typescript
96
- await authClient.twoFactor.disable({
97
- password: 'userPassword123',
98
- })
99
- ```
100
-
101
- ## 2FA 페이지 구현
102
-
103
- ```tsx
104
- // pages/two-factor.tsx
105
- import { useState } from 'react'
106
- import { authClient } from '~/lib/auth-client'
107
-
108
- export default function TwoFactorPage() {
109
- const [code, setCode] = useState('')
110
- const [error, setError] = useState('')
111
-
112
- const handleVerify = async () => {
113
- try {
114
- await authClient.twoFactor.verifyTotp({ code })
115
- // 성공 시 대시보드로 이동
116
- window.location.href = '/dashboard'
117
- } catch (e) {
118
- setError('Invalid code')
119
- }
120
- }
42
+ // 백업 코드
43
+ await authClient.twoFactor.useBackupCode({ code: 'ABCD-1234' })
44
+ await authClient.twoFactor.regenerateBackupCodes({ password })
121
45
 
122
- return (
123
- <div>
124
- <h1>2단계 인증</h1>
125
- <input
126
- type="text"
127
- value={code}
128
- onChange={(e) => setCode(e.target.value)}
129
- placeholder="6자리 코드 입력"
130
- />
131
- <button onClick={handleVerify}>확인</button>
132
- {error && <p style={{ color: 'red' }}>{error}</p>}
133
- </div>
134
- )
135
- }
46
+ // 비활성화
47
+ await authClient.twoFactor.disable({ password })
136
48
  ```