@liedsonc/core-auth-kit 2.1.4 → 2.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +802 -0
  2. package/dist/components/auth-card.d.ts +10 -0
  3. package/dist/components/auth-card.d.ts.map +1 -0
  4. package/dist/components/auth-card.js +10 -0
  5. package/dist/components/auth-form.d.ts +10 -0
  6. package/dist/components/auth-form.d.ts.map +1 -0
  7. package/dist/components/auth-form.js +21 -0
  8. package/dist/components/error-message.d.ts +6 -0
  9. package/dist/components/error-message.d.ts.map +1 -0
  10. package/dist/components/error-message.js +8 -0
  11. package/dist/components/form-field.d.ts +9 -0
  12. package/dist/components/form-field.d.ts.map +1 -0
  13. package/dist/components/form-field.js +7 -0
  14. package/dist/components/index.d.ts +9 -0
  15. package/dist/components/index.d.ts.map +1 -0
  16. package/{components/index.ts → dist/components/index.js} +8 -8
  17. package/dist/components/loading-spinner.d.ts +5 -0
  18. package/dist/components/loading-spinner.d.ts.map +1 -0
  19. package/dist/components/loading-spinner.js +6 -0
  20. package/dist/components/oauth-buttons.d.ts +11 -0
  21. package/dist/components/oauth-buttons.d.ts.map +1 -0
  22. package/dist/components/oauth-buttons.js +14 -0
  23. package/dist/components/password-input.d.ts +8 -0
  24. package/dist/components/password-input.d.ts.map +1 -0
  25. package/dist/components/password-input.js +36 -0
  26. package/dist/components/success-message.d.ts +6 -0
  27. package/dist/components/success-message.d.ts.map +1 -0
  28. package/dist/components/success-message.js +8 -0
  29. package/dist/components/ui/button.d.ts +12 -0
  30. package/dist/components/ui/button.d.ts.map +1 -0
  31. package/dist/components/ui/button.js +33 -0
  32. package/dist/components/ui/card.d.ts +9 -0
  33. package/dist/components/ui/card.d.ts.map +1 -0
  34. package/dist/components/ui/card.js +16 -0
  35. package/dist/components/ui/input.d.ts +4 -0
  36. package/dist/components/ui/input.d.ts.map +1 -0
  37. package/dist/components/ui/input.js +8 -0
  38. package/dist/components/ui/label.d.ts +6 -0
  39. package/dist/components/ui/label.d.ts.map +1 -0
  40. package/dist/components/ui/label.js +10 -0
  41. package/dist/context.d.ts +8 -0
  42. package/dist/context.d.ts.map +1 -0
  43. package/dist/context.js +13 -0
  44. package/dist/hooks/use-auth.d.ts +22 -0
  45. package/dist/hooks/use-auth.d.ts.map +1 -0
  46. package/dist/hooks/use-auth.js +112 -0
  47. package/dist/hooks/use-oauth.d.ts +6 -0
  48. package/dist/hooks/use-oauth.d.ts.map +1 -0
  49. package/dist/hooks/use-oauth.js +18 -0
  50. package/dist/index.d.ts +7 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +5 -0
  53. package/dist/pages/forgot-password/index.d.ts +2 -0
  54. package/dist/pages/forgot-password/index.d.ts.map +1 -0
  55. package/dist/pages/forgot-password/index.js +30 -0
  56. package/dist/pages/index.d.ts +6 -0
  57. package/dist/pages/index.d.ts.map +1 -0
  58. package/{pages/index.ts → dist/pages/index.js} +5 -5
  59. package/dist/pages/login/index.d.ts +2 -0
  60. package/dist/pages/login/index.d.ts.map +1 -0
  61. package/dist/pages/login/index.js +45 -0
  62. package/dist/pages/register/index.d.ts +2 -0
  63. package/dist/pages/register/index.d.ts.map +1 -0
  64. package/dist/pages/register/index.js +59 -0
  65. package/dist/pages/reset-password/index.d.ts +2 -0
  66. package/dist/pages/reset-password/index.d.ts.map +1 -0
  67. package/dist/pages/reset-password/index.js +48 -0
  68. package/dist/pages/verify-email/index.d.ts +2 -0
  69. package/dist/pages/verify-email/index.d.ts.map +1 -0
  70. package/dist/pages/verify-email/index.js +47 -0
  71. package/dist/tsconfig.build.tsbuildinfo +1 -0
  72. package/dist/types/index.d.ts +60 -0
  73. package/dist/types/index.d.ts.map +1 -0
  74. package/dist/types/index.js +1 -0
  75. package/dist/utils.d.ts +3 -0
  76. package/dist/utils.d.ts.map +1 -0
  77. package/dist/utils.js +5 -0
  78. package/package.json +15 -11
  79. package/components/auth-card.tsx +0 -49
  80. package/components/auth-form.tsx +0 -53
  81. package/components/error-message.tsx +0 -24
  82. package/components/form-field.tsx +0 -39
  83. package/components/loading-spinner.tsx +0 -19
  84. package/components/oauth-buttons.tsx +0 -49
  85. package/components/password-input.tsx +0 -93
  86. package/components/success-message.tsx +0 -24
  87. package/components/ui/button.tsx +0 -52
  88. package/components/ui/card.tsx +0 -75
  89. package/components/ui/input.tsx +0 -21
  90. package/components/ui/label.tsx +0 -25
  91. package/context.tsx +0 -26
  92. package/hooks/use-auth.ts +0 -131
  93. package/hooks/use-oauth.ts +0 -25
  94. package/index.ts +0 -28
  95. package/pages/forgot-password/index.tsx +0 -83
  96. package/pages/login/index.tsx +0 -119
  97. package/pages/register/index.tsx +0 -149
  98. package/pages/reset-password/index.tsx +0 -133
  99. package/pages/verify-email/index.tsx +0 -143
  100. package/types/index.ts +0 -34
  101. package/utils.ts +0 -6
package/README.md ADDED
@@ -0,0 +1,802 @@
1
+ # @liedsonc/core-auth-kit
2
+
3
+ This is a core authentication UI package for Next.js for lazy people like me 😂.
4
+
5
+ I don't want to make Login, Register, and Forgot Password page for every project 🤢 (sooooo boring).
6
+ That's why I created this package that makes all UI using my fav tech's `shadcn/ui`, `Tailwind CSS`, `Resend` for mailing.
7
+ Make my auth UI with a single command, and it is also customizable for your project. Just install the package and connect it with the services keys.
8
+
9
+
10
+ ## Features
11
+
12
+ - 🔐 **Complete Auth Flows** - Login, Register, Forgot Password, Reset Password, Email Verification
13
+ - 🎨 **Beautiful UI** - Built with shadcn/ui components, fully themeable and accessible
14
+ - 🔌 **Backend Agnostic** - Works with any authentication backend via `AuthClient` interface
15
+ - 📱 **Mobile-First** - Responsive design that works on all devices
16
+ - ♿ **Accessible** - WCAG compliant with proper ARIA attributes and keyboard navigation
17
+ - 🎯 **Type-Safe** - Full TypeScript support with strict typing
18
+ - 🚀 **Zero Config** - Works out-of-the-box with sensible defaults
19
+ - 🎨 **Customizable** - Override components, styles, and behavior as needed
20
+ - 🌙 **Dark Mode** - Built-in dark mode support via Tailwind CSS
21
+ - ⚙️ **Environment Configurable** - OAuth providers and settings via environment variables
22
+ - 📧 **Email Integration** - Built-in Resend email service support for verification and password reset emails
23
+
24
+ ## Installation
25
+
26
+ For plug-and-play, run **one command** from your Next.js app root (see [Plug and Play](#plug-and-play-recommended)):
27
+
28
+ ```bash
29
+ npx @liedsonc/core-auth-kit init
30
+ ```
31
+
32
+ Or install the package yourself; all UI dependencies are installed automatically:
33
+
34
+ ```bash
35
+ npm install @liedsonc/core-auth-kit
36
+ ```
37
+
38
+ ### Peer Dependencies
39
+
40
+ The following peer dependencies are required but should already be installed in your Next.js project:
41
+
42
+ - `next` (^15.0.0) - Next.js framework
43
+ - `react` (^19.0.0) - React library
44
+ - `react-dom` (^19.0.0) - React DOM library
45
+
46
+ If you're not using Next.js or these aren't installed, install them:
47
+
48
+ ```bash
49
+ npm install next react react-dom
50
+ ```
51
+
52
+ **Note:** The following dependencies are automatically installed with the package:
53
+ - `@radix-ui/react-label` - For accessible form labels
54
+ - `@radix-ui/react-slot` - For component composition
55
+ - `class-variance-authority` - For component variants
56
+ - `clsx` - For conditional class names
57
+ - `tailwind-merge` - For merging Tailwind classes
58
+
59
+ ### Email Service (Optional)
60
+
61
+ For email verification and password reset functionality, install Resend:
62
+
63
+ ```bash
64
+ npm install resend
65
+ ```
66
+
67
+ ### shadcn/ui Components
68
+
69
+ The package includes shadcn/ui components by default. Ensure your project has the shadcn/ui setup:
70
+
71
+ 1. Install shadcn/ui components (if not already installed):
72
+ ```bash
73
+ npx shadcn@latest add button input card label
74
+ ```
75
+
76
+ 2. Ensure your `tailwind.config.ts` includes the auth-ui styles:
77
+ ```ts
78
+ import type { Config } from "tailwindcss";
79
+
80
+ const config: Config = {
81
+ content: [
82
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
83
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
84
+ "./node_modules/@liedsonc/core-auth-kit/**/*.{js,ts,jsx,tsx}",
85
+ ],
86
+ // ... rest of config
87
+ };
88
+ ```
89
+
90
+ 3. Import the styles in your root layout:
91
+ ```tsx
92
+ import "@liedsonc/core-auth-kit/styles";
93
+ ```
94
+
95
+ ## Plug and Play (Recommended)
96
+
97
+ From your Next.js app root, a single command installs the package (if needed) and creates all auth pages, layout, config, and optional API route stubs:
98
+
99
+ ```bash
100
+ npx @liedsonc/core-auth-kit init
101
+ ```
102
+
103
+ The CLI installs `@liedsonc/core-auth-kit` when it is not already in your project, then scaffolds the files. Use `--force` to overwrite existing files. The CLI detects `app` vs `src/app` and `lib` vs `src/lib` automatically.
104
+
105
+ **Next steps:**
106
+
107
+ 1. Implement `lib/auth-client.ts` (or `src/lib/auth-client.ts`) with your backend (e.g. Supabase, custom API). The stub returns "NOT_IMPLEMENTED" until you replace it.
108
+ 2. Copy `.env.example` to `.env.local` and set your environment variables.
109
+ 3. If your `AuthClient` calls `/api/auth/*`, implement the scaffolded API routes in `app/api/auth/` (or `src/app/api/auth/`); each stub returns 501 until you wire it to your backend.
110
+ 4. Ensure Tailwind content includes the package and you import `@liedsonc/core-auth-kit/styles` in your root layout (see above).
111
+
112
+ After that, auth routes are available at `/login`, `/register`, `/forgot-password`, `/reset-password`, and `/verify-email`. The only required integration point is your `AuthClient` implementation; the rest is wiring and optional API handlers.
113
+
114
+ ### Scaffolded files
115
+
116
+ | Path | Purpose | What to do |
117
+ |------|---------|------------|
118
+ | `app/(auth)/layout.tsx` | Wraps auth routes with `AuthUIProvider` and config from `lib/auth-config.ts`. | Usually no change. |
119
+ | `app/(auth)/login/page.tsx` | Login page (and similar for register, forgot-password, reset-password, verify-email). | Usually no change. |
120
+ | `lib/auth-config.ts` | Builds `AuthUIConfig` (authClient, OAuth from env, redirects). | Edit only if you need custom redirects or OAuth config. |
121
+ | `lib/auth-client.ts` | **AuthClient implementation.** | **Replace the stub** with your real backend (Supabase, custom API, etc.). |
122
+ | `.env.example` | Example environment variables. | Copy to `.env.local` and fill in your values. |
123
+ | `app/api/auth/*/route.ts` | API route stubs (login, register, logout, forgot-password, reset-password, verify-email, session). | Implement each handler to call your backend; stubs return 501 until then. |
124
+
125
+ ## Environment Variables
126
+
127
+ Create a `.env.local` file (or `.env`) with the following variables:
128
+
129
+ ```bash
130
+ NEXT_PUBLIC_APP_URL=http://localhost:3000
131
+
132
+ NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN=/
133
+ NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER=/login
134
+ NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET=/login
135
+
136
+ NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED=false
137
+ NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID=your_google_client_id
138
+ NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI=http://localhost:3000/api/auth/google
139
+ OAUTH_GOOGLE_CLIENT_SECRET=your_google_client_secret
140
+
141
+ NEXT_PUBLIC_OAUTH_APPLE_ENABLED=false
142
+ NEXT_PUBLIC_OAUTH_APPLE_CLIENT_ID=your_apple_client_id
143
+ NEXT_PUBLIC_OAUTH_APPLE_REDIRECT_URI=http://localhost:3000/api/auth/apple
144
+ OAUTH_APPLE_CLIENT_SECRET=your_apple_client_secret
145
+
146
+ RESEND_API_KEY=re_your_resend_api_key
147
+ RESEND_FROM_EMAIL=noreply@yourdomain.com
148
+ RESEND_FROM_NAME=Your App Name
149
+ NEXT_PUBLIC_APP_NAME=Your App Name
150
+ ```
151
+
152
+ ### Environment Variable Reference
153
+
154
+ | Variable | Description | Required | Default |
155
+ |----------|-------------|----------|---------|
156
+ | `NEXT_PUBLIC_APP_URL` | Your application base URL | No | `http://localhost:3000` |
157
+ | `NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN` | Redirect URL after successful login | No | `/` |
158
+ | `NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER` | Redirect URL after registration | No | `/login` |
159
+ | `NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET` | Redirect URL after password reset | No | `/login` |
160
+ | `NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED` | Enable/disable Google OAuth | No | `false` |
161
+ | `NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID` | Google OAuth Client ID | Yes (if Google enabled) | - |
162
+ | `NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI` | Google OAuth redirect URI | Yes (if Google enabled) | - |
163
+ | `OAUTH_GOOGLE_CLIENT_SECRET` | Google OAuth Client Secret (server-only) | Yes (if Google enabled) | - |
164
+ | `NEXT_PUBLIC_OAUTH_APPLE_ENABLED` | Enable/disable Apple OAuth | No | `false` |
165
+ | `NEXT_PUBLIC_OAUTH_APPLE_CLIENT_ID` | Apple OAuth Client ID | Yes (if Apple enabled) | - |
166
+ | `NEXT_PUBLIC_OAUTH_APPLE_REDIRECT_URI` | Apple OAuth redirect URI | Yes (if Apple enabled) | - |
167
+ | `OAUTH_APPLE_CLIENT_SECRET` | Apple OAuth Client Secret (server-only) | Yes (if Apple enabled) | - |
168
+ | `RESEND_API_KEY` | Resend API key for sending emails | Yes (if using email features) | - |
169
+ | `RESEND_FROM_EMAIL` | Email address to send from (must be verified in Resend) | Yes (if using email features) | - |
170
+ | `RESEND_FROM_NAME` | Display name for email sender | No | - |
171
+ | `NEXT_PUBLIC_APP_NAME` | Your application name (used in emails) | No | `App` |
172
+
173
+ **Note:** Variables prefixed with `NEXT_PUBLIC_` are exposed to the browser. Secrets should NOT use this prefix.
174
+
175
+ ## Quick Start
176
+
177
+ If you ran `npx @liedsonc/core-auth-kit init`, the layout and pages already exist; go to **1. Implement AuthClient** and replace the stub in `lib/auth-client.ts` with your backend. Otherwise, follow steps 1–3 below.
178
+
179
+ ### 1. Implement AuthClient
180
+
181
+ Create an `AuthClient` that connects to your backend (or replace the stub in `lib/auth-client.ts` if you used init):
182
+
183
+ ```typescript
184
+ import type { AuthClient } from "@liedsonc/core-auth-kit";
185
+
186
+ export const myAuthClient: AuthClient = {
187
+ async login(email, password) {
188
+ const response = await fetch("/api/auth/login", {
189
+ method: "POST",
190
+ headers: { "Content-Type": "application/json" },
191
+ body: JSON.stringify({ email, password }),
192
+ });
193
+
194
+ if (!response.ok) {
195
+ return {
196
+ success: false,
197
+ error: { code: "INVALID_CREDENTIALS", message: "Invalid email or password" },
198
+ };
199
+ }
200
+
201
+ return { success: true };
202
+ },
203
+
204
+ async register(email, password) {
205
+ const response = await fetch("/api/auth/register", {
206
+ method: "POST",
207
+ headers: { "Content-Type": "application/json" },
208
+ body: JSON.stringify({ email, password }),
209
+ });
210
+
211
+ if (!response.ok) {
212
+ const data = await response.json();
213
+ return {
214
+ success: false,
215
+ error: { code: data.code || "REGISTRATION_FAILED", message: data.message },
216
+ };
217
+ }
218
+
219
+ return { success: true };
220
+ },
221
+
222
+ async logout() {
223
+ await fetch("/api/auth/logout", { method: "POST" });
224
+ },
225
+
226
+ async forgotPassword(email) {
227
+ const response = await fetch("/api/auth/forgot-password", {
228
+ method: "POST",
229
+ headers: { "Content-Type": "application/json" },
230
+ body: JSON.stringify({ email }),
231
+ });
232
+
233
+ return response.ok ? { success: true } : {
234
+ success: false,
235
+ error: { code: "FAILED", message: "Failed to send reset email" },
236
+ };
237
+ },
238
+
239
+ async resetPassword(token, newPassword) {
240
+ const response = await fetch("/api/auth/reset-password", {
241
+ method: "POST",
242
+ headers: { "Content-Type": "application/json" },
243
+ body: JSON.stringify({ token, newPassword }),
244
+ });
245
+
246
+ if (!response.ok) {
247
+ return {
248
+ success: false,
249
+ error: { code: "INVALID_TOKEN", message: "Invalid or expired token" },
250
+ };
251
+ }
252
+
253
+ return { success: true };
254
+ },
255
+
256
+ async verifyEmail(token) {
257
+ const response = await fetch("/api/auth/verify-email", {
258
+ method: "POST",
259
+ headers: { "Content-Type": "application/json" },
260
+ body: JSON.stringify({ token }),
261
+ });
262
+
263
+ if (!response.ok) {
264
+ const data = await response.json();
265
+ return {
266
+ success: false,
267
+ error: { code: data.code || "INVALID", message: data.message },
268
+ };
269
+ }
270
+
271
+ return { success: true };
272
+ },
273
+
274
+ async getSession() {
275
+ const response = await fetch("/api/auth/session");
276
+ if (!response.ok) return null;
277
+ return response.json();
278
+ },
279
+ };
280
+ ```
281
+
282
+ ### 2. Setup Provider with Environment Variables
283
+
284
+ Create a utility to load OAuth config from environment variables:
285
+
286
+ ```typescript
287
+ // lib/oauth-config.ts
288
+ import type { OAuthProvider } from "@liedsonc/core-auth-kit";
289
+
290
+ export interface OAuthProviderConfig {
291
+ provider: OAuthProvider;
292
+ enabled: boolean;
293
+ clientId?: string;
294
+ redirectUri?: string;
295
+ }
296
+
297
+ export function getOAuthProvidersFromEnv(): OAuthProviderConfig[] {
298
+ const providers: OAuthProviderConfig[] = [];
299
+
300
+ if (process.env.NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED === "true") {
301
+ providers.push({
302
+ provider: "google",
303
+ enabled: true,
304
+ clientId: process.env.NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID,
305
+ redirectUri: process.env.NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI,
306
+ });
307
+ }
308
+
309
+ if (process.env.NEXT_PUBLIC_OAUTH_APPLE_ENABLED === "true") {
310
+ providers.push({
311
+ provider: "apple",
312
+ enabled: true,
313
+ clientId: process.env.NEXT_PUBLIC_OAUTH_APPLE_CLIENT_ID,
314
+ redirectUri: process.env.NEXT_PUBLIC_OAUTH_APPLE_REDIRECT_URI,
315
+ });
316
+ }
317
+
318
+ return providers;
319
+ }
320
+ ```
321
+
322
+ Wrap your auth routes with `AuthUIProvider`:
323
+
324
+ ```tsx
325
+ // app/(auth)/layout.tsx
326
+ "use client";
327
+
328
+ import { AuthUIProvider } from "@liedsonc/core-auth-kit";
329
+ import { myAuthClient } from "@/lib/auth-client";
330
+ import { getOAuthProvidersFromEnv } from "@/lib/oauth-config";
331
+
332
+ export default function AuthLayout({ children }: { children: React.ReactNode }) {
333
+ return (
334
+ <AuthUIProvider
335
+ config={{
336
+ authClient: myAuthClient,
337
+ oauthProviders: getOAuthProvidersFromEnv(),
338
+ redirectAfterLogin: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN || "/",
339
+ redirectAfterRegister: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER || "/login",
340
+ redirectAfterReset: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET || "/login",
341
+ }}
342
+ >
343
+ {children}
344
+ </AuthUIProvider>
345
+ );
346
+ }
347
+ ```
348
+
349
+ ### 3. Create Auth Pages
350
+
351
+ Use the pre-built page components:
352
+
353
+ ```tsx
354
+ // app/(auth)/login/page.tsx
355
+ import { LoginPage } from "@liedsonc/core-auth-kit";
356
+
357
+ export default function Login() {
358
+ return <LoginPage />;
359
+ }
360
+ ```
361
+
362
+ ```tsx
363
+ // app/(auth)/register/page.tsx
364
+ import { RegisterPage } from "@liedsonc/core-auth-kit";
365
+
366
+ export default function Register() {
367
+ return <RegisterPage />;
368
+ }
369
+ ```
370
+
371
+ ```tsx
372
+ // app/(auth)/forgot-password/page.tsx
373
+ import { ForgotPasswordPage } from "@liedsonc/core-auth-kit";
374
+
375
+ export default function ForgotPassword() {
376
+ return <ForgotPasswordPage />;
377
+ }
378
+ ```
379
+
380
+ ```tsx
381
+ // app/(auth)/reset-password/page.tsx
382
+ import { ResetPasswordPage } from "@liedsonc/core-auth-kit";
383
+
384
+ export default function ResetPassword() {
385
+ return <ResetPasswordPage />;
386
+ }
387
+ ```
388
+
389
+ ```tsx
390
+ // app/(auth)/verify-email/page.tsx
391
+ import { VerifyEmailPage } from "@liedsonc/core-auth-kit";
392
+
393
+ export default function VerifyEmail() {
394
+ return <VerifyEmailPage />;
395
+ }
396
+ ```
397
+
398
+ ## Email Integration with Resend
399
+
400
+ The package includes utilities for sending verification and password reset emails via Resend. Here's how to integrate it:
401
+
402
+ ### 1. Setup Resend
403
+
404
+ 1. Sign up for a [Resend account](https://resend.com)
405
+ 2. Get your API key from the dashboard
406
+ 3. Verify your domain (or use Resend's test domain for development)
407
+ 4. Add your credentials to `.env.local`:
408
+
409
+ ```bash
410
+ RESEND_API_KEY=re_your_api_key_here
411
+ RESEND_FROM_EMAIL=noreply@yourdomain.com
412
+ RESEND_FROM_NAME=Your App Name
413
+ NEXT_PUBLIC_APP_NAME=Your App Name
414
+ ```
415
+
416
+ ### 2. Use Resend Email Service
417
+
418
+ Import and use the Resend email service in your AuthClient implementation:
419
+
420
+ ```typescript
421
+ // lib/auth-client.ts
422
+ import type { AuthClient } from "@liedsonc/core-auth-kit";
423
+ import { createResendEmailService } from "@/lib/resend-email";
424
+ import { randomBytes } from "crypto";
425
+
426
+ const emailService = createResendEmailService({
427
+ apiKey: process.env.RESEND_API_KEY!,
428
+ from: process.env.RESEND_FROM_EMAIL!,
429
+ fromName: process.env.RESEND_FROM_NAME,
430
+ appName: process.env.NEXT_PUBLIC_APP_NAME || "App",
431
+ });
432
+
433
+ const appUrl = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000";
434
+
435
+ export const myAuthClient: AuthClient = {
436
+ async register(email, password) {
437
+ // Your registration logic here
438
+ // ... save user to database
439
+
440
+ // Generate verification token
441
+ const token = randomBytes(32).toString("hex");
442
+ // Store token in database with expiration
443
+ // await db.verificationTokens.create({ email, token, expiresAt: ... });
444
+
445
+ // Send verification email
446
+ const verificationUrl = `${appUrl}/verify-email?token=${token}`;
447
+ const emailResult = await emailService.sendVerificationEmail({
448
+ email,
449
+ token,
450
+ verificationUrl,
451
+ });
452
+
453
+ if (!emailResult.success) {
454
+ return {
455
+ success: false,
456
+ error: { code: "EMAIL_SEND_FAILED", message: "Failed to send verification email" },
457
+ };
458
+ }
459
+
460
+ return { success: true };
461
+ },
462
+
463
+ async forgotPassword(email) {
464
+ // Generate reset token
465
+ const token = randomBytes(32).toString("hex");
466
+ // Store token in database with expiration (e.g., 1 hour)
467
+ // await db.resetTokens.create({ email, token, expiresAt: ... });
468
+
469
+ // Send password reset email
470
+ const resetUrl = `${appUrl}/reset-password?token=${token}`;
471
+ const emailResult = await emailService.sendPasswordResetEmail({
472
+ email,
473
+ token,
474
+ resetUrl,
475
+ expiresIn: "1 hour",
476
+ });
477
+
478
+ if (!emailResult.success) {
479
+ return {
480
+ success: false,
481
+ error: { code: "EMAIL_SEND_FAILED", message: "Failed to send reset email" },
482
+ };
483
+ }
484
+
485
+ return { success: true };
486
+ },
487
+
488
+ // ... other AuthClient methods
489
+ };
490
+ ```
491
+
492
+ ### 3. Example Implementation
493
+
494
+ See `lib/auth-client-with-resend.ts` for a complete example implementation that includes:
495
+ - Token generation and validation
496
+ - Email sending with Resend
497
+ - Token expiration handling
498
+ - Error handling
499
+
500
+ ### 4. Customizing Email Templates
501
+
502
+ The email templates are built into the `ResendEmailService` class. To customize them:
503
+
504
+ 1. Extend the `ResendEmailService` class
505
+ 2. Override the template methods (`getVerificationEmailTemplate`, `getPasswordResetEmailTemplate`)
506
+ 3. Use your custom service instance
507
+
508
+ ```typescript
509
+ class CustomEmailService extends ResendEmailService {
510
+ private getVerificationEmailTemplate({ verificationUrl, appName }: { verificationUrl: string; appName: string }): string {
511
+ // Your custom HTML template
512
+ return `...`;
513
+ }
514
+ }
515
+ ```
516
+
517
+ ### 5. Email Service API
518
+
519
+ ```typescript
520
+ import { createResendEmailService, ResendEmailService } from "@/lib/resend-email";
521
+
522
+ // Create service instance
523
+ const emailService = createResendEmailService({
524
+ apiKey: process.env.RESEND_API_KEY!,
525
+ from: process.env.RESEND_FROM_EMAIL!,
526
+ fromName: "Your App",
527
+ appName: "Your App Name",
528
+ });
529
+
530
+ // Send verification email
531
+ await emailService.sendVerificationEmail({
532
+ email: "user@example.com",
533
+ token: "verification_token",
534
+ verificationUrl: "https://yourapp.com/verify-email?token=...",
535
+ appName: "Your App", // Optional, uses service default if not provided
536
+ });
537
+
538
+ // Send password reset email
539
+ await emailService.sendPasswordResetEmail({
540
+ email: "user@example.com",
541
+ token: "reset_token",
542
+ resetUrl: "https://yourapp.com/reset-password?token=...",
543
+ appName: "Your App", // Optional
544
+ expiresIn: "1 hour", // Optional, default is "1 hour"
545
+ });
546
+ ```
547
+
548
+ ## API Reference
549
+
550
+ ### Components
551
+
552
+ #### Pages
553
+
554
+ - **`LoginPage`** - Complete login page with email/password and OAuth
555
+ - **`RegisterPage`** - Registration page with password strength indicator
556
+ - **`ForgotPasswordPage`** - Password reset request page
557
+ - **`ResetPasswordPage`** - Password reset form (requires token query param)
558
+ - **`VerifyEmailPage`** - Email verification page (requires token query param)
559
+
560
+ #### UI Components
561
+
562
+ - **`AuthCard`** - Reusable card layout for auth pages
563
+ - **`AuthForm`** - Form wrapper with loading/error states
564
+ - **`FormField`** - Form field with label and error display
565
+ - **`PasswordInput`** - Password input with show/hide toggle and strength indicator
566
+ - **`OAuthButtons`** - OAuth provider buttons (Google, Apple)
567
+ - **`ErrorMessage`** - Error message display component
568
+ - **`SuccessMessage`** - Success message display component
569
+ - **`LoadingSpinner`** - Loading spinner component
570
+
571
+ ### Hooks
572
+
573
+ #### `useAuth()`
574
+
575
+ Main authentication hook that provides all auth methods:
576
+
577
+ ```typescript
578
+ const {
579
+ login, // (email: string, password: string) => Promise<AuthResult>
580
+ register, // (email: string, password: string) => Promise<AuthResult>
581
+ logout, // () => Promise<void>
582
+ forgotPassword, // (email: string) => Promise<AuthResult>
583
+ resetPassword, // (token: string, newPassword: string) => Promise<AuthResult>
584
+ verifyEmail, // (token: string) => Promise<AuthResult>
585
+ session, // AuthSession | null
586
+ loadSession, // () => Promise<AuthSession | null>
587
+ loading, // boolean
588
+ error, // AuthError | null
589
+ clearError, // () => void
590
+ } = useAuth();
591
+ ```
592
+
593
+ #### `useOAuth(onRedirect)`
594
+
595
+ OAuth authentication hook:
596
+
597
+ ```typescript
598
+ const { signIn, loadingProvider } = useOAuth(
599
+ (provider) => `/api/auth/${provider}`
600
+ );
601
+ ```
602
+
603
+ ### Types
604
+
605
+ ```typescript
606
+ interface AuthClient {
607
+ login: (email: string, password: string) => Promise<AuthResult>;
608
+ register: (email: string, password: string) => Promise<AuthResult>;
609
+ logout: () => Promise<void>;
610
+ forgotPassword: (email: string) => Promise<AuthResult>;
611
+ resetPassword: (token: string, newPassword: string) => Promise<AuthResult>;
612
+ verifyEmail: (token: string) => Promise<AuthResult>;
613
+ getSession?: () => Promise<AuthSession | null>;
614
+ }
615
+
616
+ interface AuthUIConfig {
617
+ authClient: AuthClient;
618
+ oauthProviders?: { provider: OAuthProvider; enabled: boolean }[];
619
+ logo?: ReactNode;
620
+ redirectAfterLogin?: string;
621
+ redirectAfterRegister?: string;
622
+ redirectAfterReset?: string;
623
+ }
624
+
625
+ type AuthResult =
626
+ | { success: true }
627
+ | { success: false; error: AuthError };
628
+
629
+ interface AuthError {
630
+ code: string;
631
+ message: string;
632
+ }
633
+
634
+ type OAuthProvider = "google" | "apple";
635
+ ```
636
+
637
+ ## Customization
638
+
639
+ ### Custom Logo
640
+
641
+ ```tsx
642
+ <AuthUIProvider
643
+ config={{
644
+ authClient: myAuthClient,
645
+ logo: <img src="/logo.svg" alt="Logo" />,
646
+ }}
647
+ >
648
+ {children}
649
+ </AuthUIProvider>
650
+ ```
651
+
652
+ ### OAuth Configuration via Environment Variables
653
+
654
+ Enable/disable OAuth providers and configure credentials via environment variables:
655
+
656
+ ```bash
657
+ NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED=true
658
+ NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID=your_client_id
659
+ NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI=https://yourapp.com/api/auth/google
660
+ OAUTH_GOOGLE_CLIENT_SECRET=your_client_secret
661
+ ```
662
+
663
+ The `getOAuthProvidersFromEnv()` utility automatically reads these and configures providers.
664
+
665
+ ### Custom Redirects
666
+
667
+ Set redirects via environment variables or config:
668
+
669
+ ```tsx
670
+ <AuthUIProvider
671
+ config={{
672
+ authClient: myAuthClient,
673
+ redirectAfterLogin: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN || "/dashboard",
674
+ redirectAfterRegister: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER || "/onboarding",
675
+ redirectAfterReset: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET || "/login?reset=success",
676
+ }}
677
+ >
678
+ {children}
679
+ </AuthUIProvider>
680
+ ```
681
+
682
+ ### Using Individual Components
683
+
684
+ You can also use components individually to build custom pages:
685
+
686
+ ```tsx
687
+ import { AuthCard, AuthForm, FormField, PasswordInput, Button } from "@liedsonc/core-auth-kit";
688
+
689
+ export function CustomLoginPage() {
690
+ return (
691
+ <AuthCard title="Sign In">
692
+ <AuthForm onSubmit={handleSubmit}>
693
+ <FormField label="Email" htmlFor="email">
694
+ <Input id="email" type="email" />
695
+ </FormField>
696
+ <FormField label="Password" htmlFor="password">
697
+ <PasswordInput id="password" />
698
+ </FormField>
699
+ <Button type="submit">Sign In</Button>
700
+ </AuthForm>
701
+ </AuthCard>
702
+ );
703
+ }
704
+ ```
705
+
706
+ ## Production Setup
707
+
708
+ ### 1. Environment Variables
709
+
710
+ Copy `.env.example` to `.env.local` and fill in your production values:
711
+
712
+ ```bash
713
+ cp .env.example .env.local
714
+ ```
715
+
716
+ **Important:** Never commit `.env.local` to version control. Add it to `.gitignore`.
717
+
718
+ ### 2. OAuth Provider Setup
719
+
720
+ #### Google OAuth
721
+
722
+ 1. Go to [Google Cloud Console](https://console.cloud.google.com/)
723
+ 2. Create a new project or select existing
724
+ 3. Enable Google+ API
725
+ 4. Create OAuth 2.0 credentials
726
+ 5. Add authorized redirect URIs
727
+ 6. Copy Client ID and Client Secret to `.env.local`
728
+
729
+ #### Apple OAuth
730
+
731
+ 1. Go to [Apple Developer Portal](https://developer.apple.com/)
732
+ 2. Create an App ID
733
+ 3. Create a Services ID
734
+ 4. Configure Sign in with Apple
735
+ 5. Add redirect URIs
736
+ 6. Copy Client ID and Client Secret to `.env.local`
737
+
738
+ ### 3. Build and Deploy
739
+
740
+ ```bash
741
+ npm run build
742
+ npm start
743
+ ```
744
+
745
+ ## Styling
746
+
747
+ The package uses Tailwind CSS and follows shadcn/ui conventions. Customize colors via CSS variables:
748
+
749
+ ```css
750
+ :root {
751
+ --primary: 222.2 47.4% 11.2%;
752
+ --primary-foreground: 210 40% 98%;
753
+ /* ... other variables */
754
+ }
755
+ ```
756
+
757
+ See [shadcn/ui theming](https://ui.shadcn.com/docs/theming) for details.
758
+
759
+ ## Security Considerations
760
+
761
+ - **No User Enumeration**: Error messages don't reveal if an email exists
762
+ - **Secure Defaults**: Password inputs prevent autofill leaks
763
+ - **CSRF Protection**: Implement CSRF tokens in your `AuthClient`
764
+ - **Rate Limiting**: Implement rate limiting in your backend
765
+ - **Token Security**: Handle tokens securely in your `AuthClient`
766
+ - **Environment Variables**: Never expose secrets in client-side code (use `NEXT_PUBLIC_` prefix only for public values)
767
+
768
+ ## Browser Support
769
+
770
+ - Chrome (latest)
771
+ - Firefox (latest)
772
+ - Safari (latest)
773
+ - Edge (latest)
774
+
775
+ ## Project Structure
776
+
777
+ ```
778
+ core-auth-kit/
779
+ ├── auth-ui/ # Package source code
780
+ │ ├── components/ # UI components
781
+ │ ├── hooks/ # React hooks
782
+ │ ├── pages/ # Page components
783
+ │ ├── types/ # TypeScript types
784
+ │ ├── styles/ # CSS styles
785
+ │ └── index.ts # Main export
786
+ ├── app/ # Example Next.js app
787
+ ├── lib/ # Utilities (oauth-config, auth-client)
788
+ ├── .env.example # Environment variables template
789
+ └── README.md # This file
790
+ ```
791
+
792
+ ## Contributing
793
+
794
+ Contributions are welcome! Please read our contributing guidelines first.
795
+
796
+ ## License
797
+
798
+ MIT
799
+
800
+ ## Support
801
+
802
+ For issues, questions, or contributions, please open an issue on GitHub.