hazo_auth 1.6.0 → 1.6.2

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 (74) hide show
  1. package/README.md +191 -19
  2. package/SETUP_CHECKLIST.md +190 -65
  3. package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts +9 -0
  4. package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts.map +1 -0
  5. package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.js +82 -0
  6. package/dist/app/api/hazo_auth/library_photos/route.d.ts +9 -0
  7. package/dist/app/api/hazo_auth/library_photos/route.d.ts.map +1 -1
  8. package/dist/app/api/hazo_auth/library_photos/route.js +31 -6
  9. package/dist/cli/generate.d.ts +6 -1
  10. package/dist/cli/generate.d.ts.map +1 -1
  11. package/dist/cli/generate.js +101 -34
  12. package/dist/cli/index.js +64 -11
  13. package/dist/cli/init.d.ts +2 -0
  14. package/dist/cli/init.d.ts.map +1 -0
  15. package/dist/cli/init.js +206 -0
  16. package/dist/client.d.ts +8 -0
  17. package/dist/client.d.ts.map +1 -0
  18. package/dist/client.js +25 -0
  19. package/dist/components/layouts/email_verification/index.d.ts +2 -1
  20. package/dist/components/layouts/email_verification/index.d.ts.map +1 -1
  21. package/dist/components/layouts/email_verification/index.js +3 -2
  22. package/dist/components/layouts/forgot_password/index.d.ts +3 -1
  23. package/dist/components/layouts/forgot_password/index.d.ts.map +1 -1
  24. package/dist/components/layouts/forgot_password/index.js +3 -2
  25. package/dist/components/layouts/my_settings/components/editable_field.js +1 -1
  26. package/dist/components/layouts/my_settings/components/password_change_dialog.js +1 -1
  27. package/dist/components/layouts/my_settings/components/profile_picture_display.js +1 -1
  28. package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.js +1 -1
  29. package/dist/components/layouts/my_settings/components/profile_picture_library_tab.js +4 -4
  30. package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.js +4 -4
  31. package/dist/components/layouts/my_settings/index.js +1 -1
  32. package/dist/components/layouts/shared/components/profile_pic_menu.js +2 -2
  33. package/dist/lib/auth_utility_config.server.js +2 -2
  34. package/dist/lib/services/profile_picture_service.d.ts +34 -2
  35. package/dist/lib/services/profile_picture_service.d.ts.map +1 -1
  36. package/dist/lib/services/profile_picture_service.js +157 -15
  37. package/dist/lib/services/user_profiles_cache.d.ts +76 -0
  38. package/dist/lib/services/user_profiles_cache.d.ts.map +1 -0
  39. package/dist/lib/services/user_profiles_cache.js +141 -0
  40. package/dist/lib/services/user_profiles_service.d.ts +17 -0
  41. package/dist/lib/services/user_profiles_service.d.ts.map +1 -1
  42. package/dist/lib/services/user_profiles_service.js +136 -44
  43. package/dist/lib/user_profiles_config.server.d.ts +15 -0
  44. package/dist/lib/user_profiles_config.server.d.ts.map +1 -0
  45. package/dist/lib/user_profiles_config.server.js +23 -0
  46. package/dist/page_components/forgot_password.d.ts +19 -0
  47. package/dist/page_components/forgot_password.d.ts.map +1 -0
  48. package/dist/page_components/forgot_password.js +36 -0
  49. package/dist/page_components/index.d.ts +7 -0
  50. package/dist/page_components/index.d.ts.map +1 -0
  51. package/dist/page_components/index.js +9 -0
  52. package/dist/page_components/login.d.ts +26 -0
  53. package/dist/page_components/login.d.ts.map +1 -0
  54. package/dist/page_components/login.js +40 -0
  55. package/dist/page_components/my_settings.d.ts +64 -0
  56. package/dist/page_components/my_settings.d.ts.map +1 -0
  57. package/dist/page_components/my_settings.js +67 -0
  58. package/dist/page_components/register.d.ts +25 -0
  59. package/dist/page_components/register.d.ts.map +1 -0
  60. package/dist/page_components/register.js +43 -0
  61. package/dist/page_components/reset_password.d.ts +25 -0
  62. package/dist/page_components/reset_password.d.ts.map +1 -0
  63. package/dist/page_components/reset_password.js +43 -0
  64. package/dist/page_components/verify_email.d.ts +21 -0
  65. package/dist/page_components/verify_email.d.ts.map +1 -0
  66. package/dist/page_components/verify_email.js +36 -0
  67. package/dist/server/routes/index.d.ts +1 -0
  68. package/dist/server/routes/index.d.ts.map +1 -1
  69. package/dist/server/routes/index.js +1 -0
  70. package/dist/server/routes/library_photo.d.ts +2 -0
  71. package/dist/server/routes/library_photo.d.ts.map +1 -0
  72. package/dist/server/routes/library_photo.js +3 -0
  73. package/hazo_auth_config.example.ini +25 -5
  74. package/package.json +33 -1
package/README.md CHANGED
@@ -26,32 +26,61 @@ npm install hazo_auth
26
26
 
27
27
  ## Quick Start
28
28
 
29
- ### 1. Install the package
29
+ The fastest way to get started is using the CLI commands:
30
30
 
31
31
  ```bash
32
+ # 1. Install the package
32
33
  npm install hazo_auth
34
+
35
+ # 2. Initialize your project (creates directories, copies config files)
36
+ npx hazo_auth init
37
+
38
+ # 3. Generate API routes and pages
39
+ npx hazo_auth generate-routes --pages
40
+
41
+ # 4. Set up environment variables
42
+ cp .env.local.example .env.local
43
+ # Edit .env.local and add your ZEPTOMAIL_API_KEY
44
+
45
+ # 5. Start your dev server
46
+ npm run dev
33
47
  ```
34
48
 
35
- ### 2. Copy configuration files
49
+ That's it! Visit `http://localhost:3000/hazo_auth/login` to see the login page.
50
+
51
+ ### CLI Commands
36
52
 
37
53
  ```bash
38
- cp node_modules/hazo_auth/hazo_auth_config.example.ini ./hazo_auth_config.ini
39
- cp node_modules/hazo_auth/hazo_notify_config.example.ini ./hazo_notify_config.ini
54
+ npx hazo_auth init # Initialize project (creates dirs, copies config)
55
+ npx hazo_auth generate-routes # Generate API routes only
56
+ npx hazo_auth generate-routes --pages # Generate API routes + pages
57
+ npx hazo_auth validate # Check your setup and configuration
58
+ npx hazo_auth --help # Show all commands
40
59
  ```
41
60
 
42
- ### 3. Set up environment variables
61
+ ### Using Zero-Config Page Components
43
62
 
44
- Create a `.env.local` file:
63
+ The generated pages import from `hazo_auth/pages/*` which provides zero-config components:
45
64
 
46
- ```env
47
- ZEPTOMAIL_API_KEY=your_api_key_here
65
+ ```typescript
66
+ // Generated app/hazo_auth/login/page.tsx
67
+ import { LoginPage } from "hazo_auth/pages/login";
68
+ export default LoginPage;
48
69
  ```
49
70
 
50
- ### 4. Set up the database
71
+ Available zero-config pages:
72
+ - `LoginPage` - Login form with sensible defaults
73
+ - `RegisterPage` - Registration with password requirements
74
+ - `ForgotPasswordPage` - Password reset request
75
+ - `ResetPasswordPage` - Set new password
76
+ - `VerifyEmailPage` - Email verification
77
+ - `MySettingsPage` - User profile and settings
78
+
79
+ All pages work out-of-the-box with no props required!
51
80
 
52
- Run the database setup SQL script (see [Database Setup](#database-setup)).
81
+ ### Manual Setup (Advanced)
53
82
 
54
- ### 5. Import and use components
83
+ If you prefer manual control, you can use the layout components directly:
55
84
 
56
85
  ```typescript
57
86
  // Import layout components
@@ -77,6 +106,132 @@ import { hazo_get_auth } from "hazo_auth/lib/auth/hazo_get_auth.server";
77
106
 
78
107
  ---
79
108
 
109
+ ## Required Dependencies
110
+
111
+ hazo_auth uses shadcn/ui components. Install the required dependencies in your project:
112
+
113
+ ```bash
114
+ # Required for all auth pages
115
+ npx shadcn@latest add button input label
116
+
117
+ # Required for My Settings page
118
+ npx shadcn@latest add dialog tabs switch avatar dropdown-menu
119
+
120
+ # Required for toast notifications
121
+ npx shadcn@latest add sonner
122
+ ```
123
+
124
+ **Add Toaster to your app layout:**
125
+
126
+ ```tsx
127
+ // app/layout.tsx
128
+ import { Toaster } from "sonner";
129
+
130
+ export default function RootLayout({ children }) {
131
+ return (
132
+ <html>
133
+ <body>
134
+ {children}
135
+ <Toaster />
136
+ </body>
137
+ </html>
138
+ );
139
+ }
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Client vs Server Imports
145
+
146
+ hazo_auth provides separate entry points for client and server code to avoid bundling Node.js modules in the browser:
147
+
148
+ ### Client Components
149
+
150
+ For client components (browser-safe, no Node.js dependencies):
151
+
152
+ ```typescript
153
+ // Use hazo_auth/client for client components
154
+ import {
155
+ ProfilePicMenu,
156
+ use_auth_status,
157
+ use_hazo_auth,
158
+ cn
159
+ } from "hazo_auth/client";
160
+ ```
161
+
162
+ ### Server Components / API Routes
163
+
164
+ For server-side code (API routes, Server Components):
165
+
166
+ ```typescript
167
+ // Use the main hazo_auth export for server-side code
168
+ import { hazo_get_auth, get_config_value } from "hazo_auth";
169
+ import { hazo_get_user_profiles } from "hazo_auth";
170
+ ```
171
+
172
+ ### Why This Matters
173
+
174
+ If you import from the main `hazo_auth` entry in a client component, you'll get bundling errors like:
175
+ ```
176
+ Module not found: Can't resolve 'fs'
177
+ ```
178
+
179
+ Use `hazo_auth/client` to avoid this.
180
+
181
+ ---
182
+
183
+ ## Dark Mode / Theming
184
+
185
+ hazo_auth supports dark mode via CSS custom properties. To enable dark mode:
186
+
187
+ ### 1. Import the theme CSS
188
+
189
+ Copy the variables file to your project:
190
+
191
+ ```bash
192
+ cp node_modules/hazo_auth/src/styles/hazo-auth-variables.css ./app/hazo-auth-theme.css
193
+ ```
194
+
195
+ Import in your `globals.css`:
196
+
197
+ ```css
198
+ @import "./hazo-auth-theme.css";
199
+ ```
200
+
201
+ ### 2. CSS Variables Reference
202
+
203
+ You can customize the theme by overriding these variables:
204
+
205
+ ```css
206
+ :root {
207
+ /* Backgrounds */
208
+ --hazo-bg-subtle: #f8fafc; /* Light background */
209
+ --hazo-bg-muted: #f1f5f9; /* Slightly darker background */
210
+
211
+ /* Text */
212
+ --hazo-text-primary: #0f172a; /* Primary text */
213
+ --hazo-text-secondary: #334155; /* Secondary text */
214
+ --hazo-text-muted: #64748b; /* Muted/subtle text */
215
+
216
+ /* Borders */
217
+ --hazo-border: #e2e8f0; /* Standard border */
218
+ }
219
+
220
+ .dark {
221
+ /* Dark mode overrides */
222
+ --hazo-bg-subtle: #18181b;
223
+ --hazo-bg-muted: #27272a;
224
+ --hazo-text-primary: #fafafa;
225
+ --hazo-text-secondary: #d4d4d8;
226
+ --hazo-text-muted: #a1a1aa;
227
+ --hazo-border: #3f3f46;
228
+ }
229
+ ```
230
+
231
+ The dark class is typically added by next-themes or similar theme providers.
232
+
233
+ ---
234
+
80
235
  ## Configuration Setup
81
236
 
82
237
  After installing the package, you need to set up configuration files in your project root:
@@ -415,7 +570,25 @@ The package exports components through these paths:
415
570
  // Main entry point - exports all public APIs
416
571
  import { ... } from "hazo_auth";
417
572
 
418
- // Layout components - one export per auth flow
573
+ // Zero-config page components (recommended for quick setup)
574
+ import { LoginPage } from "hazo_auth/pages/login";
575
+ import { RegisterPage } from "hazo_auth/pages/register";
576
+ import { ForgotPasswordPage } from "hazo_auth/pages/forgot_password";
577
+ import { ResetPasswordPage } from "hazo_auth/pages/reset_password";
578
+ import { VerifyEmailPage } from "hazo_auth/pages/verify_email";
579
+ import { MySettingsPage } from "hazo_auth/pages/my_settings";
580
+
581
+ // Or import all pages at once
582
+ import {
583
+ LoginPage,
584
+ RegisterPage,
585
+ ForgotPasswordPage,
586
+ ResetPasswordPage,
587
+ VerifyEmailPage,
588
+ MySettingsPage
589
+ } from "hazo_auth/pages";
590
+
591
+ // Layout components - for custom implementations
419
592
  import { LoginLayout } from "hazo_auth/components/layouts/login";
420
593
  import { RegisterLayout } from "hazo_auth/components/layouts/register";
421
594
  import { ForgotPasswordLayout } from "hazo_auth/components/layouts/forgot_password";
@@ -903,22 +1076,21 @@ This compiles the `src/` directory to `dist/` with:
903
1076
 
904
1077
  ### Package Exports
905
1078
 
906
- The `package.json` exports field defines the public API. The package exposes only the main entry points:
1079
+ The `package.json` exports field defines the public API:
907
1080
 
908
1081
  ```json
909
1082
  {
910
1083
  "exports": {
911
1084
  ".": "./dist/index.js",
1085
+ "./pages": "./dist/page_components/index.js",
1086
+ "./pages/login": "./dist/page_components/login.js",
1087
+ "./pages/register": "./dist/page_components/register.js",
912
1088
  "./components/layouts/login": "./dist/components/layouts/login/index.js",
913
1089
  "./components/layouts/register": "./dist/components/layouts/register/index.js",
914
- "./components/layouts/forgot_password": "./dist/components/layouts/forgot_password/index.js",
915
- "./components/layouts/reset_password": "./dist/components/layouts/reset_password/index.js",
916
- "./components/layouts/email_verification": "./dist/components/layouts/email_verification/index.js",
917
- "./components/layouts/my_settings": "./dist/components/layouts/my_settings/index.js",
918
- "./components/layouts/user_management": "./dist/components/layouts/user_management/index.js",
919
1090
  "./components/layouts/shared": "./dist/components/layouts/shared/index.js",
920
1091
  "./lib/auth/hazo_get_auth.server": "./dist/lib/auth/hazo_get_auth.server.js",
921
- "./server": "./dist/server/index.js"
1092
+ "./server": "./dist/server/index.js",
1093
+ "./server/routes": "./dist/server/routes/index.js"
922
1094
  }
923
1095
  }
924
1096
  ```
@@ -2,6 +2,33 @@
2
2
 
3
3
  This checklist provides step-by-step instructions for setting up the `hazo_auth` package in your Next.js project. AI assistants can follow this guide to ensure complete and correct setup.
4
4
 
5
+ ## Quick Start (Recommended)
6
+
7
+ The fastest way to set up hazo_auth:
8
+
9
+ ```bash
10
+ # 1. Install the package
11
+ npm install hazo_auth
12
+
13
+ # 2. Initialize project (creates directories, copies config files)
14
+ npx hazo_auth init
15
+
16
+ # 3. Generate API routes and pages
17
+ npx hazo_auth generate-routes --pages
18
+
19
+ # 4. Set up environment variables
20
+ cp .env.local.example .env.local
21
+ # Edit .env.local and add ZEPTOMAIL_API_KEY
22
+
23
+ # 5. Start dev server and test
24
+ npm run dev
25
+ # Visit http://localhost:3000/hazo_auth/login
26
+ ```
27
+
28
+ If this works, skip to [Phase 6: Verification Tests](#phase-6-verification-tests).
29
+
30
+ ---
31
+
5
32
  ## Pre-flight Checks
6
33
 
7
34
  Before starting, verify your project meets these requirements:
@@ -33,7 +60,79 @@ ls node_modules/hazo_auth/package.json
33
60
  # Expected: file exists
34
61
  ```
35
62
 
36
- ### Step 1.2: Copy configuration files
63
+ ### Step 1.2: Install Required shadcn/ui Components
64
+
65
+ hazo_auth uses shadcn/ui components. Install the required dependencies:
66
+
67
+ **For all auth pages (login, register, etc.):**
68
+ ```bash
69
+ npx shadcn@latest add button input label
70
+ ```
71
+
72
+ **For My Settings page:**
73
+ ```bash
74
+ npx shadcn@latest add dialog tabs switch avatar dropdown-menu
75
+ ```
76
+
77
+ **For toast notifications:**
78
+ ```bash
79
+ npx shadcn@latest add sonner
80
+ ```
81
+
82
+ **Add Toaster to your app layout:**
83
+
84
+ Edit `app/layout.tsx` and add the Toaster component:
85
+
86
+ ```tsx
87
+ import { Toaster } from "sonner";
88
+
89
+ export default function RootLayout({ children }) {
90
+ return (
91
+ <html>
92
+ <body>
93
+ {children}
94
+ <Toaster />
95
+ </body>
96
+ </html>
97
+ );
98
+ }
99
+ ```
100
+
101
+ ### Step 1.4: Enable Dark Mode Support (Optional)
102
+
103
+ hazo_auth components support dark mode via CSS custom properties. Add the CSS variables to your global styles:
104
+
105
+ **Copy the CSS variables file:**
106
+ ```bash
107
+ cp node_modules/hazo_auth/src/styles/hazo-auth-variables.css ./app/hazo-auth-theme.css
108
+ ```
109
+
110
+ **Import in your global styles (`app/globals.css`):**
111
+ ```css
112
+ @import "./hazo-auth-theme.css";
113
+ ```
114
+
115
+ Or add the variables directly to your CSS - see the file for all available variables.
116
+
117
+ ### Step 1.5: Initialize project (Recommended)
118
+
119
+ Use the CLI to automatically set up directories and copy config files:
120
+
121
+ ```bash
122
+ npx hazo_auth init
123
+ ```
124
+
125
+ This command:
126
+ - Creates `public/profile_pictures/library/` directory
127
+ - Creates `public/profile_pictures/uploads/` directory
128
+ - Creates `data/` directory (for SQLite database)
129
+ - Copies `hazo_auth_config.ini` and `hazo_notify_config.ini`
130
+ - Copies profile picture library images
131
+ - Creates `.env.local.example` template
132
+
133
+ ### Step 1.2b: Manual config setup (Alternative)
134
+
135
+ If you prefer manual setup:
37
136
 
38
137
  ```bash
39
138
  cp node_modules/hazo_auth/hazo_auth_config.example.ini ./hazo_auth_config.ini
@@ -424,86 +523,92 @@ export { GET } from "hazo_auth/server/routes/profile_picture_filename";
424
523
 
425
524
  Create page files for each auth flow.
426
525
 
427
- ### Step 5.1: Create auth pages
526
+ ### Step 5.1: Generate pages automatically (Recommended)
428
527
 
429
- **Login page** - `app/(auth)/login/page.tsx`:
430
- ```typescript
431
- import { LoginLayout } from "hazo_auth/components/layouts/login";
432
-
433
- export default function LoginPage() {
434
- return <LoginLayout />;
435
- }
528
+ ```bash
529
+ npx hazo_auth generate-routes --pages
436
530
  ```
437
531
 
438
- **Register page** - `app/(auth)/register/page.tsx`:
439
- ```typescript
440
- import { RegisterLayout } from "hazo_auth/components/layouts/register";
532
+ This generates both API routes and page routes. The generated pages use zero-config components that work out of the box.
441
533
 
442
- export default function RegisterPage() {
443
- return <RegisterLayout />;
444
- }
534
+ **Generated pages:**
535
+ ```
536
+ app/hazo_auth/
537
+ ├── login/page.tsx
538
+ ├── register/page.tsx
539
+ ├── forgot_password/page.tsx
540
+ ├── reset_password/page.tsx
541
+ ├── verify_email/page.tsx
542
+ └── my_settings/page.tsx
445
543
  ```
446
544
 
447
- **Forgot password page** - `app/(auth)/forgot-password/page.tsx`:
448
- ```typescript
449
- import { ForgotPasswordLayout } from "hazo_auth/components/layouts/forgot_password";
545
+ ### Step 5.2: Manual page creation (Alternative)
450
546
 
451
- export default function ForgotPasswordPage() {
452
- return <ForgotPasswordLayout />;
453
- }
454
- ```
547
+ If you prefer manual setup or need custom paths, create these files:
455
548
 
456
- **Reset password page** - `app/(auth)/reset-password/page.tsx`:
549
+ **Login page** - `app/hazo_auth/login/page.tsx`:
457
550
  ```typescript
458
- import { ResetPasswordLayout } from "hazo_auth/components/layouts/reset_password";
551
+ import { LoginPage } from "hazo_auth/pages/login";
552
+ export default LoginPage;
553
+ ```
459
554
 
460
- export default function ResetPasswordPage() {
461
- return <ResetPasswordLayout />;
462
- }
555
+ **Register page** - `app/hazo_auth/register/page.tsx`:
556
+ ```typescript
557
+ import { RegisterPage } from "hazo_auth/pages/register";
558
+ export default RegisterPage;
463
559
  ```
464
560
 
465
- **Email verification page** - `app/(auth)/verify-email/page.tsx`:
561
+ **Forgot password page** - `app/hazo_auth/forgot_password/page.tsx`:
466
562
  ```typescript
467
- import { EmailVerificationLayout } from "hazo_auth/components/layouts/email_verification";
563
+ import { ForgotPasswordPage } from "hazo_auth/pages/forgot_password";
564
+ export default ForgotPasswordPage;
565
+ ```
468
566
 
469
- export default function VerifyEmailPage() {
470
- return <EmailVerificationLayout />;
471
- }
567
+ **Reset password page** - `app/hazo_auth/reset_password/page.tsx`:
568
+ ```typescript
569
+ import { ResetPasswordPage } from "hazo_auth/pages/reset_password";
570
+ export default ResetPasswordPage;
472
571
  ```
473
572
 
474
- **My settings page** - `app/(auth)/my-settings/page.tsx`:
573
+ **Email verification page** - `app/hazo_auth/verify_email/page.tsx`:
475
574
  ```typescript
476
- import { MySettingsLayout } from "hazo_auth/components/layouts/my_settings";
575
+ import { VerifyEmailPage } from "hazo_auth/pages/verify_email";
576
+ export default VerifyEmailPage;
577
+ ```
477
578
 
478
- export default function MySettingsPage() {
479
- return <MySettingsLayout />;
480
- }
579
+ **My settings page** - `app/hazo_auth/my_settings/page.tsx`:
580
+ ```typescript
581
+ import { MySettingsPage } from "hazo_auth/pages/my_settings";
582
+ export default MySettingsPage;
481
583
  ```
482
584
 
483
- ### Step 5.2: Create layout for auth pages (optional)
585
+ ### Step 5.3: Custom page routes (Advanced)
586
+
587
+ If you need custom paths or want to wrap pages with your own layout:
484
588
 
485
- `app/(auth)/layout.tsx`:
486
589
  ```typescript
487
- export default function AuthLayout({
488
- children,
489
- }: {
490
- children: React.ReactNode;
491
- }) {
590
+ // app/(auth)/login/page.tsx
591
+ import { LoginPage } from "hazo_auth/pages/login";
592
+
593
+ export default function CustomLoginPage() {
492
594
  return (
493
- <div className="min-h-screen flex items-center justify-center bg-background">
494
- {children}
595
+ <div className="min-h-screen flex items-center justify-center">
596
+ <LoginPage
597
+ redirectRoute="/dashboard"
598
+ successMessage="Welcome back!"
599
+ />
495
600
  </div>
496
601
  );
497
602
  }
498
603
  ```
499
604
 
500
605
  **Checklist:**
501
- - [ ] Login page created (`/login`)
502
- - [ ] Register page created (`/register`)
503
- - [ ] Forgot password page created (`/forgot-password`)
504
- - [ ] Reset password page created (`/reset-password`)
505
- - [ ] Email verification page created (`/verify-email`)
506
- - [ ] My settings page created (`/my-settings`)
606
+ - [ ] Login page created (`/hazo_auth/login`)
607
+ - [ ] Register page created (`/hazo_auth/register`)
608
+ - [ ] Forgot password page created (`/hazo_auth/forgot_password`)
609
+ - [ ] Reset password page created (`/hazo_auth/reset_password`)
610
+ - [ ] Email verification page created (`/hazo_auth/verify_email`)
611
+ - [ ] My settings page created (`/hazo_auth/my_settings`)
507
612
 
508
613
  ---
509
614
 
@@ -578,15 +683,22 @@ curl -s http://localhost:3000/api/hazo_auth/library_photos | jq
578
683
  **Expected response:**
579
684
  ```json
580
685
  {
581
- "photos": [
582
- {"url": "/profile_pictures/library/...", "name": "..."},
583
- ...
584
- ]
686
+ "success": true,
687
+ "categories": ["Cars", "Young Cartoons"],
688
+ "source": "project"
585
689
  }
586
690
  ```
587
691
 
588
- **If library photos not showing:**
589
- - Copy profile pictures from `node_modules/hazo_auth/public/profile_pictures/library/` to `public/profile_pictures/library/`
692
+ The `source` field indicates where photos are served from:
693
+ - `"project"` - Photos are in your project's `public/profile_pictures/library/`
694
+ - `"node_modules"` - Photos are served from `node_modules/hazo_auth/public/` via API route
695
+
696
+ **Test paginated photos:**
697
+ ```bash
698
+ curl -s "http://localhost:3000/api/hazo_auth/library_photos?category=Cars&page=1&page_size=5" | jq
699
+ ```
700
+
701
+ **Note:** Library photos work automatically whether they're copied to your project or still in node_modules. The API will serve them from node_modules as a fallback.
590
702
 
591
703
  ### Test 6: Visit Pages in Browser
592
704
 
@@ -596,10 +708,10 @@ npm run dev
596
708
  ```
597
709
 
598
710
  Visit each page and verify it loads:
599
- - [ ] `http://localhost:3000/login` - Login form displays
600
- - [ ] `http://localhost:3000/register` - Registration form displays
601
- - [ ] `http://localhost:3000/forgot-password` - Forgot password form displays
602
- - [ ] `http://localhost:3000/my-settings` - Settings page displays (after login)
711
+ - [ ] `http://localhost:3000/hazo_auth/login` - Login form displays
712
+ - [ ] `http://localhost:3000/hazo_auth/register` - Registration form displays
713
+ - [ ] `http://localhost:3000/hazo_auth/forgot_password` - Forgot password form displays
714
+ - [ ] `http://localhost:3000/hazo_auth/my_settings` - Settings page displays (after login)
603
715
 
604
716
  ---
605
717
 
@@ -620,13 +732,26 @@ Visit each page and verify it loads:
620
732
  **Symptoms:** Avatar shows fallback initials, library photos empty.
621
733
 
622
734
  **Solutions:**
623
- 1. Copy library photos:
735
+ 1. **Run init command** (copies library photos automatically):
736
+ ```bash
737
+ npx hazo_auth init
738
+ ```
739
+
740
+ 2. **Or manually copy library photos:**
624
741
  ```bash
625
742
  mkdir -p public/profile_pictures/library
626
743
  cp -r node_modules/hazo_auth/public/profile_pictures/library/* public/profile_pictures/library/
627
744
  ```
628
- 2. Verify `library_photos` API route exists
629
- 3. Check file permissions on `public/profile_pictures/`
745
+
746
+ 3. **Check API response source:**
747
+ ```bash
748
+ curl -s http://localhost:3000/api/hazo_auth/library_photos | jq '.source'
749
+ ```
750
+ - If `"node_modules"` - Photos are being served from the package (slower but works)
751
+ - If `"project"` - Photos are in your public folder (optimal)
752
+
753
+ 4. Verify `library_photos` and `library_photo` API routes exist
754
+ 5. Check file permissions on `public/profile_pictures/`
630
755
 
631
756
  ### Issue: Database connection failed
632
757
 
@@ -0,0 +1,9 @@
1
+ import { NextRequest, NextResponse } from "next/server";
2
+ export declare const dynamic = "force-dynamic";
3
+ export declare function GET(request: NextRequest, { params }: {
4
+ params: {
5
+ category: string;
6
+ filename: string;
7
+ };
8
+ }): Promise<NextResponse<unknown>>;
9
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/app/api/hazo_auth/library_photo/[category]/[filename]/route.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AASxD,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAevC,wBAAsB,GAAG,CACvB,OAAO,EAAE,WAAW,EACpB,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,kCA4E/D"}
@@ -0,0 +1,82 @@
1
+ // file_description: API route to serve library photos from node_modules fallback
2
+ // This route is used when library photos haven't been copied to the project's public folder
3
+ // section: imports
4
+ import { NextResponse } from "next/server";
5
+ import { get_library_photo_path } from "../../../../../../lib/services/profile_picture_service";
6
+ import { create_app_logger } from "../../../../../../lib/app_logger";
7
+ import { get_filename, get_line_number } from "../../../../../../lib/utils/api_route_helpers";
8
+ import fs from "fs";
9
+ import path from "path";
10
+ // section: route_config
11
+ // Cache library photos for 1 hour (they don't change)
12
+ export const dynamic = 'force-dynamic';
13
+ // section: constants
14
+ const MIME_TYPES = {
15
+ ".jpg": "image/jpeg",
16
+ ".jpeg": "image/jpeg",
17
+ ".png": "image/png",
18
+ ".gif": "image/gif",
19
+ ".webp": "image/webp",
20
+ ".svg": "image/svg+xml",
21
+ };
22
+ const CACHE_MAX_AGE = 3600; // 1 hour in seconds
23
+ // section: api_handler
24
+ export async function GET(request, { params }) {
25
+ const logger = create_app_logger();
26
+ const { category, filename } = params;
27
+ try {
28
+ // Validate inputs to prevent path traversal
29
+ if (category.includes("..") ||
30
+ category.includes("/") ||
31
+ category.includes("\\") ||
32
+ filename.includes("..") ||
33
+ filename.includes("/") ||
34
+ filename.includes("\\")) {
35
+ logger.warn("library_photo_invalid_path", {
36
+ filename: get_filename(),
37
+ line_number: get_line_number(),
38
+ category,
39
+ requested_filename: filename,
40
+ });
41
+ return NextResponse.json({ error: "Invalid path" }, { status: 400 });
42
+ }
43
+ // Get the physical file path
44
+ const photo_path = get_library_photo_path(category, filename);
45
+ if (!photo_path) {
46
+ logger.warn("library_photo_not_found", {
47
+ filename: get_filename(),
48
+ line_number: get_line_number(),
49
+ category,
50
+ requested_filename: filename,
51
+ });
52
+ return NextResponse.json({ error: "Photo not found" }, { status: 404 });
53
+ }
54
+ // Read the file
55
+ const file_buffer = fs.readFileSync(photo_path);
56
+ const ext = path.extname(filename).toLowerCase();
57
+ const content_type = MIME_TYPES[ext] || "application/octet-stream";
58
+ // Return the image with caching headers
59
+ return new NextResponse(file_buffer, {
60
+ status: 200,
61
+ headers: {
62
+ "Content-Type": content_type,
63
+ "Content-Length": file_buffer.length.toString(),
64
+ "Cache-Control": `public, max-age=${CACHE_MAX_AGE}, immutable`,
65
+ "X-Library-Source": "node_modules",
66
+ },
67
+ });
68
+ }
69
+ catch (error) {
70
+ const error_message = error instanceof Error ? error.message : "Unknown error";
71
+ const error_stack = error instanceof Error ? error.stack : undefined;
72
+ logger.error("library_photo_error", {
73
+ filename: get_filename(),
74
+ line_number: get_line_number(),
75
+ category,
76
+ requested_filename: filename,
77
+ error_message,
78
+ error_stack,
79
+ });
80
+ return NextResponse.json({ error: "Failed to serve photo" }, { status: 500 });
81
+ }
82
+ }