@kood/claude-code 0.1.6 → 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 (75) 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 +103 -255
  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/library/better-auth/2fa.md +27 -115
  23. package/templates/tanstack-start/docs/library/better-auth/advanced.md +22 -105
  24. package/templates/tanstack-start/docs/library/better-auth/index.md +17 -66
  25. package/templates/tanstack-start/docs/library/better-auth/plugins.md +11 -88
  26. package/templates/tanstack-start/docs/library/better-auth/session.md +12 -92
  27. package/templates/tanstack-start/docs/library/better-auth/setup.md +9 -91
  28. package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +30 -358
  29. package/templates/tanstack-start/docs/library/prisma/config.md +27 -327
  30. package/templates/tanstack-start/docs/library/prisma/crud.md +46 -174
  31. package/templates/tanstack-start/docs/library/prisma/index.md +23 -113
  32. package/templates/tanstack-start/docs/library/prisma/relations.md +31 -153
  33. package/templates/tanstack-start/docs/library/prisma/schema.md +40 -217
  34. package/templates/tanstack-start/docs/library/prisma/setup.md +12 -112
  35. package/templates/tanstack-start/docs/library/prisma/transactions.md +20 -110
  36. package/templates/tanstack-start/docs/library/tanstack-query/index.md +12 -99
  37. package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +28 -107
  38. package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +44 -146
  39. package/templates/tanstack-start/docs/library/tanstack-query/setup.md +11 -70
  40. package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +33 -127
  41. package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +49 -149
  42. package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +19 -112
  43. package/templates/tanstack-start/docs/library/tanstack-start/index.md +33 -80
  44. package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +28 -106
  45. package/templates/tanstack-start/docs/library/tanstack-start/routing.md +21 -118
  46. package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +34 -246
  47. package/templates/tanstack-start/docs/library/tanstack-start/setup.md +6 -39
  48. package/templates/tanstack-start/docs/library/zod/basic-types.md +33 -145
  49. package/templates/tanstack-start/docs/library/zod/complex-types.md +32 -156
  50. package/templates/tanstack-start/docs/library/zod/index.md +22 -150
  51. package/templates/tanstack-start/docs/library/zod/transforms.md +20 -129
  52. package/templates/tanstack-start/docs/library/zod/validation.md +39 -155
  53. package/templates/hono/docs/commands/git.md +0 -145
  54. package/templates/hono/docs/mcp/context7.md +0 -106
  55. package/templates/hono/docs/mcp/index.md +0 -176
  56. package/templates/hono/docs/mcp/sequential-thinking.md +0 -101
  57. package/templates/hono/docs/mcp/serena.md +0 -269
  58. package/templates/hono/docs/mcp/sgrep.md +0 -105
  59. package/templates/hono/docs/skills/gemini-review/SKILL.md +0 -220
  60. package/templates/hono/docs/skills/gemini-review/references/checklists.md +0 -136
  61. package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +0 -303
  62. package/templates/npx/docs/commands/git.md +0 -145
  63. package/templates/npx/docs/mcp/index.md +0 -60
  64. package/templates/npx/docs/skills/gemini-review/SKILL.md +0 -220
  65. package/templates/npx/docs/skills/gemini-review/references/checklists.md +0 -134
  66. package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +0 -301
  67. package/templates/tanstack-start/docs/commands/git.md +0 -145
  68. package/templates/tanstack-start/docs/mcp/context7.md +0 -204
  69. package/templates/tanstack-start/docs/mcp/index.md +0 -177
  70. package/templates/tanstack-start/docs/mcp/sequential-thinking.md +0 -180
  71. package/templates/tanstack-start/docs/mcp/serena.md +0 -269
  72. package/templates/tanstack-start/docs/mcp/sgrep.md +0 -174
  73. package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +0 -220
  74. package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +0 -144
  75. 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
+ - [ ] 제목/본문 명확한 크기 차이
@@ -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
  ```
@@ -1,138 +1,55 @@
1
1
  # Better Auth - 고급 기능
2
2
 
3
- > **상위 문서**: [Better Auth](./index.md)
4
-
5
- ## CAPTCHA 보호
3
+ ## CAPTCHA
6
4
 
7
5
  ```typescript
8
- import { betterAuth } from 'better-auth'
6
+ // 서버
9
7
  import { captcha } from 'better-auth/plugins'
10
-
11
- export const auth = betterAuth({
12
- plugins: [
13
- captcha({
14
- provider: 'recaptcha', // 'recaptcha' | 'hcaptcha'
15
- siteKey: process.env.RECAPTCHA_SITE_KEY!,
16
- secretKey: process.env.RECAPTCHA_SECRET_KEY!,
17
- protectEndpoints: ['/sign-up/email', '/sign-in/email'],
18
- }),
19
- ],
20
- })
8
+ plugins: [captcha({
9
+ provider: 'recaptcha',
10
+ siteKey: SITE_KEY, secretKey: SECRET_KEY,
11
+ protectEndpoints: ['/sign-up/email', '/sign-in/email'],
12
+ })]
21
13
 
22
14
  // 클라이언트
23
15
  import { captchaClient } from 'better-auth/client/plugins'
24
-
25
- const authClient = createAuthClient({
26
- plugins: [
27
- captchaClient({
28
- siteKey: process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY!,
29
- }),
30
- ],
31
- })
32
-
33
- // CAPTCHA는 보호된 요청에 자동 포함됨
34
- await authClient.signUp.email({
35
- email: 'user@example.com',
36
- password: 'SecurePassword123!',
37
- })
16
+ plugins: [captchaClient({ siteKey: SITE_KEY })]
38
17
  ```
39
18
 
40
- ## SSO (Single Sign-On)
19
+ ## SSO
41
20
 
42
21
  ```typescript
43
- // Provider ID로 SSO 로그인
44
- const res = await authClient.signIn.sso({
45
- providerId: 'example-provider-id',
46
- callbackURL: '/dashboard',
47
- })
22
+ await authClient.signIn.sso({ providerId: 'provider-id', callbackURL: '/dashboard' })
48
23
  ```
49
24
 
50
- ## SIWE (Sign-In with Ethereum)
51
-
52
- ### 서버 설정
25
+ ## SIWE (Ethereum)
53
26
 
54
27
  ```typescript
55
- import { betterAuth } from 'better-auth'
28
+ // 서버
56
29
  import { siwe } from 'better-auth/plugins'
30
+ plugins: [siwe({ domain: 'example.com', uri: 'https://example.com' })]
57
31
 
58
- export const auth = betterAuth({
59
- plugins: [
60
- siwe({
61
- domain: 'example.com',
62
- uri: 'https://example.com',
63
- statement: 'Sign in with your Ethereum account',
64
- }),
65
- ],
66
- })
67
- ```
68
-
69
- ### 클라이언트 사용
70
-
71
- ```typescript
72
- import { siweClient } from 'better-auth/client/plugins'
73
- import { ethers } from 'ethers'
74
-
75
- const authClient = createAuthClient({
76
- plugins: [siweClient()],
77
- })
78
-
79
- // Nonce 가져오기
32
+ // 클라이언트
80
33
  const { data: nonce } = await authClient.siwe.getNonce()
81
-
82
- // 메시지 생성 및 서명
83
- const provider = new ethers.BrowserProvider(window.ethereum)
84
- const signer = await provider.getSigner()
85
- const address = await signer.getAddress()
86
-
87
- const message = await authClient.siwe.prepareMessage({
88
- address,
89
- nonce: nonce.nonce,
90
- })
91
-
34
+ const message = await authClient.siwe.prepareMessage({ address, nonce: nonce.nonce })
92
35
  const signature = await signer.signMessage(message)
93
-
94
- // 검증 및 로그인
95
- await authClient.siwe.signIn({
96
- message,
97
- signature,
98
- })
36
+ await authClient.siwe.signIn({ message, signature })
99
37
  ```
100
38
 
101
39
  ## Stateless 모드
102
40
 
103
- 데이터베이스 없이 사용:
104
-
105
41
  ```typescript
106
- import { betterAuth } from 'better-auth'
107
-
42
+ // DB 없이 소셜 로그인만
108
43
  export const auth = betterAuth({
109
- // 데이터베이스 설정 없음 - 자동으로 stateless 모드
110
- socialProviders: {
111
- google: {
112
- clientId: process.env.GOOGLE_CLIENT_ID,
113
- clientSecret: process.env.GOOGLE_CLIENT_SECRET,
114
- },
115
- },
44
+ socialProviders: { google: { clientId, clientSecret } },
116
45
  })
117
- ```
118
-
119
- ### Redis와 함께 하이브리드 모드
120
-
121
- ```typescript
122
- import { betterAuth } from 'better-auth'
123
- import { redis } from './redis'
124
46
 
47
+ // Redis 하이브리드
125
48
  export const auth = betterAuth({
126
49
  secondaryStorage: {
127
- get: async (key) => await redis.get(key),
128
- set: async (key, value, ttl) => await redis.set(key, value, 'EX', ttl),
129
- delete: async (key) => await redis.del(key),
130
- },
131
- session: {
132
- cookieCache: {
133
- maxAge: 5 * 60, // 5분
134
- refreshCache: false,
135
- },
50
+ get: (key) => redis.get(key),
51
+ set: (key, value, ttl) => redis.set(key, value, 'EX', ttl),
52
+ delete: (key) => redis.del(key),
136
53
  },
137
54
  })
138
55
  ```