@payez/next-mvp 4.1.7 โ†’ 4.1.9

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 (154) hide show
  1. package/README.md +792 -792
  2. package/dist/auth/better-auth.js +15 -3
  3. package/dist/components/account/MobileNavDrawer.js +18 -18
  4. package/dist/components/account/UserAvatarMenu.js +1 -1
  5. package/dist/components/admin/AlertSettingsTab.js +40 -40
  6. package/dist/components/admin/LoggingSettingsTab.js +28 -28
  7. package/dist/pages/login/page.js +28 -28
  8. package/dist/pages/settings/EnhancedSettingsPage.js +17 -17
  9. package/package.json +1 -1
  10. package/scripts/dev-broker.ps1 +35 -35
  11. package/scripts/dev-local.ps1 +45 -45
  12. package/src/api/auth-handler.ts +548 -548
  13. package/src/api-handlers/account/change-password.ts +142 -142
  14. package/src/api-handlers/account/update-phone.ts +79 -79
  15. package/src/api-handlers/account/verify-email.ts +125 -125
  16. package/src/api-handlers/account/verify-sms.ts +125 -125
  17. package/src/api-handlers/admin/analytics.ts +443 -443
  18. package/src/api-handlers/admin/audit.ts +223 -223
  19. package/src/api-handlers/admin/index.ts +63 -63
  20. package/src/api-handlers/admin/redis-sessions.ts +251 -251
  21. package/src/api-handlers/admin/sessions.ts +318 -318
  22. package/src/api-handlers/admin/site-logs.ts +365 -365
  23. package/src/api-handlers/admin/users.ts +242 -242
  24. package/src/api-handlers/admin/vibe-data.ts +324 -324
  25. package/src/api-handlers/auth/refresh.ts +682 -682
  26. package/src/api-handlers/auth/signout.ts +199 -199
  27. package/src/api-handlers/auth/status.ts +20 -20
  28. package/src/api-handlers/auth/update-session.ts +110 -110
  29. package/src/api-handlers/auth/verify-code.ts +112 -112
  30. package/src/api-handlers/session/refresh-viability.ts +36 -36
  31. package/src/api-handlers/test/force-expire.ts +60 -60
  32. package/src/auth/auth-decision.ts +229 -229
  33. package/src/auth/better-auth.ts +15 -3
  34. package/src/auth/route-config.ts +219 -219
  35. package/src/auth/types/auth-types.ts +555 -555
  36. package/src/auth/types/index.ts +7 -7
  37. package/src/auth/utils/idp-client.ts +445 -445
  38. package/src/auth/utils/index.ts +6 -6
  39. package/src/auth/utils/token-utils.ts +243 -243
  40. package/src/client/AuthContext.tsx +143 -143
  41. package/src/client/fetch-with-auth.ts +47 -47
  42. package/src/components/SessionSync.tsx +138 -138
  43. package/src/components/SignalRHealthCheck.tsx +131 -131
  44. package/src/components/account/MobileNavDrawer.tsx +305 -305
  45. package/src/components/account/UserAvatarMenu.tsx +266 -266
  46. package/src/components/account/index.ts +13 -13
  47. package/src/components/admin/AlertSettingsTab.tsx +728 -728
  48. package/src/components/admin/AnalyticsTab.tsx +703 -703
  49. package/src/components/admin/DataBrowserTab.tsx +505 -505
  50. package/src/components/admin/LoggingSettingsTab.tsx +665 -665
  51. package/src/components/admin/SessionsTab.tsx +414 -414
  52. package/src/components/admin/StatsTab.tsx +379 -379
  53. package/src/components/admin/VibeAdminLayout.tsx +187 -187
  54. package/src/components/admin/index.ts +59 -59
  55. package/src/components/auth/FederatedAuthSection.tsx +95 -95
  56. package/src/components/auth/ModeAwareLoginPage.tsx +135 -135
  57. package/src/components/auth/ModeAwareSignupPage.tsx +267 -267
  58. package/src/components/auth/TraditionalAuthSection.tsx +99 -99
  59. package/src/components/recovery/CompleteStep.tsx +36 -36
  60. package/src/components/recovery/InitiateRecoveryStep.tsx +68 -68
  61. package/src/components/recovery/SelectMethodStep.tsx +73 -73
  62. package/src/components/recovery/SetPasswordStep.tsx +97 -97
  63. package/src/components/recovery/VerifyCodeStep.tsx +90 -90
  64. package/src/components/reserved/ReservedRecoveryWarning.tsx +160 -160
  65. package/src/components/reserved/ReservedStatusBox.tsx +118 -118
  66. package/src/components/ui/BetaBadge.tsx +58 -58
  67. package/src/components/ui/Footer.tsx +93 -93
  68. package/src/config/env.ts +57 -57
  69. package/src/config/logger.ts +62 -62
  70. package/src/config/vibe-log-transport.ts +264 -264
  71. package/src/hooks/useAuth.ts +117 -117
  72. package/src/hooks/useAuthSettings.ts +97 -97
  73. package/src/hooks/useAvailableProviders.ts +120 -120
  74. package/src/hooks/usePasswordValidation.ts +127 -127
  75. package/src/hooks/usePublicAuthSettings.ts +149 -149
  76. package/src/hooks/useSessionExpiration.ts +101 -101
  77. package/src/hooks/useViabilitySession.ts +336 -336
  78. package/src/index.ts +60 -60
  79. package/src/lib/api-handler.ts +643 -643
  80. package/src/lib/app-slug.ts +178 -178
  81. package/src/lib/geolocation.ts +265 -265
  82. package/src/lib/idp-fetch.ts +110 -110
  83. package/src/lib/jwt-decode.ts +82 -82
  84. package/src/lib/roles.ts +177 -177
  85. package/src/lib/site-logger.ts +245 -245
  86. package/src/lib/standardized-client-api.ts +901 -901
  87. package/src/lib/test-aware-get-token.ts +41 -41
  88. package/src/lib/user-agent-parser.ts +252 -252
  89. package/src/logging/api/admin-analytics.ts +51 -51
  90. package/src/logging/api/audit-log.ts +53 -53
  91. package/src/logging/components/AdminAnalyticsLayout.tsx +49 -49
  92. package/src/logging/components/AuditLogViewer.tsx +125 -125
  93. package/src/logging/components/ErrorMetricsCard.tsx +98 -98
  94. package/src/logging/components/HealthMetricsCard.tsx +70 -70
  95. package/src/logging/hooks/useAdminAnalytics.ts +22 -22
  96. package/src/logging/hooks/useAuditLog.ts +24 -24
  97. package/src/logging/hooks/useErrorMetrics.ts +40 -40
  98. package/src/logging/hooks/useHealthMetrics.ts +44 -44
  99. package/src/logging/index.ts +18 -18
  100. package/src/logging/types/analytics.ts +81 -81
  101. package/src/logging/types/audit.ts +31 -31
  102. package/src/logging/types/index.ts +3 -3
  103. package/src/middleware/create-middleware.ts +663 -663
  104. package/src/middleware/rbac-check.ts +279 -279
  105. package/src/middleware/twofa-presets.ts +224 -224
  106. package/src/pages/admin-login/page.tsx +221 -221
  107. package/src/pages/admin-page-permissions/PagePermissionsAdminPage.tsx +527 -527
  108. package/src/pages/admin-page-permissions/index.ts +7 -7
  109. package/src/pages/admin-roles/RolesAdminPage.tsx +533 -533
  110. package/src/pages/admin-roles/modals.tsx +469 -469
  111. package/src/pages/client-admin/ClientSiteAdminPage.tsx +382 -382
  112. package/src/pages/client-admin/index.ts +33 -33
  113. package/src/pages/coming-soon/page.tsx +83 -83
  114. package/src/pages/login/page.tsx +456 -456
  115. package/src/pages/profile/EnhancedProfilePage.tsx +485 -485
  116. package/src/pages/profile/index.ts +9 -9
  117. package/src/pages/profile/page.tsx +166 -166
  118. package/src/pages/recovery/page.tsx +234 -234
  119. package/src/pages/roles/MyRolesPage.tsx +211 -211
  120. package/src/pages/roles/components.tsx +294 -294
  121. package/src/pages/roles/index.ts +17 -17
  122. package/src/pages/security/EnhancedSecurityPage.tsx +565 -565
  123. package/src/pages/security/index.ts +9 -9
  124. package/src/pages/security/page.tsx +507 -507
  125. package/src/pages/settings/EnhancedSettingsPage.tsx +642 -642
  126. package/src/pages/settings/index.ts +9 -9
  127. package/src/pages/settings/page.tsx +47 -47
  128. package/src/pages/showcase/ShowcasePage.tsx +532 -532
  129. package/src/pages/showcase/index.ts +13 -13
  130. package/src/pages/test-env/EmergencyLogoutPage.tsx +180 -180
  131. package/src/pages/test-env/JwtInspectPage.tsx +456 -456
  132. package/src/pages/test-env/RefreshTokenPage.tsx +157 -157
  133. package/src/pages/test-env/TestEnvPage.tsx +118 -118
  134. package/src/pages/test-env/index.ts +25 -25
  135. package/src/pages/verify-code/page.tsx +652 -652
  136. package/src/routes/account/update-phone.ts +13 -13
  137. package/src/routes/auth/logout.ts +108 -108
  138. package/src/routes/auth/nextauth.ts +45 -45
  139. package/src/routes/auth/settings.ts +75 -75
  140. package/src/routes/auth/viability.ts +224 -224
  141. package/src/server/auth-guard.ts +170 -170
  142. package/src/server/slim-middleware.ts +117 -117
  143. package/src/server/with-auth.ts +93 -93
  144. package/src/stores/authStore.ts +1899 -1899
  145. package/src/templates/instrumentation.ts +41 -41
  146. package/src/utils/logout.ts +30 -30
  147. package/src/vibe/client.ts +590 -590
  148. package/src/vibe/enterprise-auth.ts +208 -208
  149. package/src/vibe/errors.ts +185 -185
  150. package/src/vibe/generic.ts +431 -431
  151. package/src/vibe/hooks/index.ts +367 -367
  152. package/src/vibe/index.ts +132 -132
  153. package/src/vibe/sessions.ts +551 -551
  154. package/src/vibe/types.ts +577 -577
package/README.md CHANGED
@@ -1,792 +1,792 @@
1
- # @payez/next-mvp
2
-
3
- Drop-in authentication for Next.js. One package, zero secret management in production.
4
-
5
- ```bash
6
- npm install @payez/next-mvp next-auth
7
- ```
8
-
9
- ## How Secrets Work
10
-
11
- You never manage signing keys or OAuth credentials directly. The package resolves them automatically at startup based on your environment.
12
-
13
- | Environment | How it works | Secrets in your config? |
14
- |-------------|-------------|------------------------|
15
- | **Dev** | App calls IDP broker on your private network. One API key in `.env.local`. | One key (rotatable via CLI) |
16
- | **Production** | App calls a cluster-internal endpoint. Network boundary = identity. | None |
17
- | **Enterprise** | App uses an issued license key against your own or our IDP. | One key (rotatable via CLI) |
18
-
19
- **In production, there are no secrets to configure, rotate, or leak.** The app proves its identity by being inside the cluster.
20
-
21
- In dev, you have one key. Rotate it anytime:
22
-
23
- ```bash
24
- npx @payez/cli secret rotate
25
- ```
26
-
27
- Full architecture: [SECRET-MANAGEMENT-ARCHITECTURE.md](../../docs/SECRET-MANAGEMENT-ARCHITECTURE.md)
28
-
29
- ## Features
30
-
31
- - **Zero-secret production deployment** โ€” no signing keys, no OAuth secrets in your env
32
- - **Complete authentication flow** โ€” login, logout, session management, password recovery
33
- - **Pre-built UI components** โ€” themed login, recovery, and verify-code pages
34
- - **Automatic token refresh** โ€” built-in refresh token handling with Redis session backing
35
- - **Google OAuth + 2FA** โ€” pre-configured providers, MFA with email/SMS
36
- - **Themeable** โ€” branding, colors, and layout via ThemeProvider
37
- - **Next.js 14/15** โ€” App Router, React Server Components, middleware-ready
38
-
39
- ## Installation
40
-
41
- ```bash
42
- npm install @payez/next-mvp next-auth
43
- # or
44
- yarn add @payez/next-mvp next-auth
45
- ```
46
-
47
- ### Peer Dependencies
48
-
49
- Ensure you have these installed:
50
-
51
- ```bash
52
- npm install next@^14.0.0 next-auth@^4.24.7 react@^18.2.0 react-dom@^18.2.0
53
- ```
54
-
55
- ---
56
-
57
- ## Development Scripts
58
-
59
- PayEz MVP includes convenient development scripts for getting started quickly:
60
-
61
- ### `npm run dev:local`
62
-
63
- **Local Development Mode** - Perfect for first-time setup and testing without an external IDP:
64
- - Auto-generates `NEXTAUTH_SECRET` for you
65
- - No external IDP connection required
66
- - Great for UI development and testing
67
-
68
- ```bash
69
- npm run dev:local
70
- ```
71
-
72
- This will:
73
- 1. Generate a secure random `NEXTAUTH_SECRET`
74
- 2. Display the secret (save it to your `.env.local`)
75
- 3. Start the Next.js dev server on port 3000
76
-
77
- ### `npm run dev:broker`
78
-
79
- **Broker Mode** - Production-like authentication with PayEz IDP:
80
- - Uses OAuth/OIDC flow with PayEz IDP
81
- - Client assertion authentication
82
- - Required for testing real authentication flows
83
- - **This is a core feature for PayEz MVP users**
84
-
85
- ```bash
86
- npm run dev:broker
87
- ```
88
-
89
- This will:
90
- 1. Enable broker mode (`USE_BROKER_MODE=true`)
91
- 2. Set client ID for IDP authentication
92
- 3. Start the Next.js dev server on port 3000
93
- 4. Automatically kills any existing process on port 3000
94
-
95
- **Custom Port & Client ID:**
96
- ```bash
97
- # In your consuming project's package.json
98
- "scripts": {
99
- "dev:broker": "pwsh -NoProfile -ExecutionPolicy Bypass -File node_modules/@payez/next-mvp/scripts/dev-broker.ps1 -ClientId 2 -Port 3400"
100
- }
101
- ```
102
-
103
- ### Which Script to Use?
104
-
105
- | Scenario | Script | When to Use |
106
- |----------|--------|-------------|
107
- | ๐ŸŽจ UI Development | `dev:local` | Building components, testing UI flows |
108
- | ๐Ÿ” Auth Testing | `dev:broker` | Testing real OAuth flows, token management |
109
- | ๐Ÿš€ Production-like | `dev:broker` | Testing with actual IDP integration |
110
-
111
- ---
112
-
113
- ## Quick Start (App Router with UI Components)
114
-
115
- ### 1. Configure Next.js
116
-
117
- Add to your `next.config.ts`:
118
-
119
- ```typescript
120
- import type { NextConfig } from "next";
121
-
122
- const nextConfig: NextConfig = {
123
- transpilePackages: ['@payez/next-mvp'],
124
- };
125
-
126
- export default nextConfig;
127
- ```
128
-
129
- ### 2. Set Environment Variables
130
-
131
- Create `.env.local` (or `.env.development`) in your project root:
132
-
133
- ```bash
134
- # PayEz IDP Configuration (required)
135
- CLIENT_ID=your_client_slug_from_payez # e.g., "payez_idp_admin_web"
136
- IDP_URL=https://idp.payez.net # or http://localhost:32785 for local dev
137
-
138
- # NextAuth trusts request headers for OAuth callback URLs
139
- AUTH_TRUST_HOST=true
140
-
141
- # NEXTAUTH_SECRET - DO NOT SET!
142
- # The MVP broker fetches this securely from IDP at startup.
143
- # Only set manually if you need to override the IDP-provided secret.
144
-
145
- # Optional
146
- REDIS_URL=redis://localhost:6379 # For session storage
147
- NEXT_PUBLIC_IDP_BASE_URL=https://idp.payez.net # For client-side redirects
148
- ```
149
-
150
- > **Note:** `NEXTAUTH_SECRET` is intentionally omitted. The MVP automatically fetches it from the IDP at startup using the broker pattern. See [Environment Variables Reference](#environment-variables-reference) for details.
151
-
152
- ### 3. Create NextAuth API Route
153
-
154
- Create `app/api/auth/[...nextauth]/route.ts`:
155
-
156
- ```typescript
157
- /**
158
- * NextAuth API Route Handler
159
- * Uses pre-configured handler from @payez/next-mvp
160
- */
161
- export { GET, POST } from '@payez/next-mvp/routes/auth/nextauth';
162
- ```
163
-
164
- ### 4. Wrap Your App with Providers
165
-
166
- Create `app/providers.tsx`:
167
-
168
- ```typescript
169
- 'use client';
170
-
171
- import { SessionProvider } from 'next-auth/react';
172
- import { ThemeProvider } from '@payez/next-mvp/theme';
173
-
174
- export function Providers({ children }: { children: React.ReactNode }) {
175
- return (
176
- <SessionProvider>
177
- <ThemeProvider>
178
- {children}
179
- </ThemeProvider>
180
- </SessionProvider>
181
- );
182
- }
183
- ```
184
-
185
- Update `app/layout.tsx`:
186
-
187
- ```typescript
188
- import { Providers } from './providers';
189
-
190
- export default function RootLayout({
191
- children,
192
- }: {
193
- children: React.ReactNode;
194
- }) {
195
- return (
196
- <html lang="en">
197
- <body>
198
- <Providers>
199
- {children}
200
- </Providers>
201
- </body>
202
- </html>
203
- );
204
- }
205
- ```
206
-
207
- ### 5. Add Authentication Pages
208
-
209
- **Login Page** - `app/account-auth/login/page.tsx`:
210
-
211
- ```typescript
212
- 'use client';
213
-
214
- import LoginPage from '@payez/next-mvp/dist/pages/login';
215
-
216
- export default function LoginPageWrapper() {
217
- return <LoginPage />;
218
- }
219
- ```
220
-
221
- **Password Recovery** - `app/account-auth/recovery/page.tsx`:
222
-
223
- ```typescript
224
- 'use client';
225
-
226
- import RecoveryPage from '@payez/next-mvp/dist/pages/recovery';
227
-
228
- export default function RecoveryPageWrapper() {
229
- return <RecoveryPage />;
230
- }
231
- ```
232
-
233
- **Verify Code (2FA)** - `app/account-auth/verify-code/page.tsx`:
234
-
235
- ```typescript
236
- 'use client';
237
-
238
- import VerifyCodePage from '@payez/next-mvp/dist/pages/verify-code';
239
-
240
- export default function VerifyCodePageWrapper() {
241
- return <VerifyCodePage />;
242
- }
243
- ```
244
-
245
- ### 6. Protect Routes with Authentication
246
-
247
- **Server-side protection:**
248
-
249
- ```typescript
250
- import { getServerSession } from 'next-auth';
251
- import { redirect } from 'next/navigation';
252
-
253
- export default async function DashboardPage() {
254
- const session = await getServerSession();
255
-
256
- if (!session) {
257
- redirect('/account-auth/login');
258
- }
259
-
260
- return (
261
- <div>
262
- <h1>Welcome, {session.user?.email}</h1>
263
- </div>
264
- );
265
- }
266
- ```
267
-
268
- **Client-side hook:**
269
-
270
- ```typescript
271
- 'use client';
272
-
273
- import { useSession } from 'next-auth/react';
274
-
275
- export default function ProfilePage() {
276
- const { data: session, status } = useSession();
277
-
278
- if (status === 'loading') return <div>Loading...</div>;
279
- if (status === 'unauthenticated') return <div>Access Denied</div>;
280
-
281
- return <div>Logged in as {session?.user?.email}</div>;
282
- }
283
- ```
284
-
285
- ---
286
-
287
- ## Advanced: V2 Middleware-Based Setup
288
-
289
- For applications requiring middleware-based route protection:
290
-
291
- ### 1. Configure Public Routes
292
-
293
- Create `src/lib/auth.ts`:
294
-
295
- ```typescript
296
- import { configurePublicRoutes, createAuthOptions } from '@payez/next-mvp';
297
- import CredentialsProvider from 'next-auth/providers/credentials';
298
-
299
- // Define routes that do NOT require authentication
300
- const publicRoutes = [
301
- '/',
302
- '/login',
303
- '/api/health',
304
- '/api/public/*', // Wildcard example
305
- ];
306
-
307
- configurePublicRoutes(publicRoutes);
308
-
309
- export const authOptions = createAuthOptions({
310
- credentialsProvider: CredentialsProvider,
311
- // Additional NextAuthOptions can be passed here
312
- });
313
-
314
- export { authOptions as GET, authOptions as POST } from './auth';
315
- ```
316
-
317
- ### 2. Setup NextAuth API Route
318
-
319
- **For Pages Router (`pages/api/auth/[...nextauth].ts`):**
320
-
321
- ```typescript
322
- import NextAuth from 'next-auth';
323
- import { authOptions } from '../../../src/lib/auth';
324
-
325
- export default NextAuth(authOptions);
326
- ```
327
-
328
- **For App Router (`app/api/auth/[...nextauth]/route.ts`):**
329
-
330
- ```typescript
331
- export { GET, POST } from '../../../src/lib/auth';
332
- ```
333
-
334
- ### 3. Implement Middleware
335
-
336
- Create `middleware.ts` at project root:
337
-
338
- ```typescript
339
- import { createMvpMiddleware } from '@payez/next-mvp';
340
-
341
- export default createMvpMiddleware();
342
-
343
- export const config = {
344
- matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
345
- };
346
- ```
347
-
348
- ### 4. Use `fetchWithAuth` for Protected API Calls
349
-
350
- ```typescript
351
- import { fetchWithAuth } from '@payez/next-mvp';
352
-
353
- async function fetchData() {
354
- try {
355
- const response = await fetchWithAuth('/api/protected-data');
356
- const data = await response.json();
357
- console.log(data);
358
- } catch (error) {
359
- console.error('Failed to fetch protected data:', error);
360
- }
361
- }
362
- ```
363
-
364
- ### 5. Session Viability API Handler
365
-
366
- **For Pages Router (`pages/api/session/viability.ts`):**
367
-
368
- ```typescript
369
- import viabilityHandler from '@payez/next-mvp/api-handlers/session/viability';
370
-
371
- export default viabilityHandler;
372
- ```
373
-
374
- **For App Router (`app/api/session/viability/route.ts`):**
375
-
376
- ```typescript
377
- export { default as GET } from '@payez/next-mvp/api-handlers/session/viability';
378
- ```
379
-
380
- ---
381
-
382
- ## Custom Theming
383
-
384
- Customize branding and colors:
385
-
386
- ```typescript
387
- // lib/mvp-theme-config.ts
388
- import { ThemeConfig } from '@payez/next-mvp/theme';
389
-
390
- const customTheme: ThemeConfig = {
391
- branding: {
392
- companyName: "Your Company",
393
- logoUrl: "/logo.svg",
394
- logoAlt: "Your Company Logo"
395
- },
396
- colors: {
397
- primary: "#3b82f6", // Blue
398
- primaryHover: "#2563eb",
399
- secondary: "#10b981", // Green
400
- danger: "#ef4444", // Red
401
- text: "#1f2937",
402
- textLight: "#6b7280",
403
- background: "#ffffff",
404
- backgroundAlt: "#f9fafb",
405
- border: "#e5e7eb"
406
- },
407
- layout: {
408
- maxWidth: "28rem", // max-w-md
409
- padding: "1.5rem", // p-6
410
- borderRadius: "0.5rem" // rounded-lg
411
- }
412
- };
413
-
414
- export default customTheme;
415
- ```
416
-
417
- Then use in your Providers:
418
-
419
- ```typescript
420
- import customTheme from '@/lib/mvp-theme-config';
421
-
422
- export function Providers({ children }: { children: React.ReactNode }) {
423
- return (
424
- <SessionProvider>
425
- <ThemeProvider theme={customTheme}>
426
- {children}
427
- </ThemeProvider>
428
- </SessionProvider>
429
- );
430
- }
431
- ```
432
-
433
- ---
434
-
435
- ## API Routes
436
-
437
- Access pre-built API handlers:
438
-
439
- ```typescript
440
- // Session validation
441
- import { GET as validateSession } from '@payez/next-mvp/routes/auth/session';
442
-
443
- // Token refresh
444
- import { POST as refreshToken } from '@payez/next-mvp/routes/auth/refresh';
445
-
446
- // Logout
447
- import { POST as logout } from '@payez/next-mvp/routes/auth/logout';
448
- ```
449
-
450
- ---
451
-
452
- ## Environment Variables Reference
453
-
454
- | Variable | Required | Description |
455
- |----------|----------|-------------|
456
- | `CLIENT_ID` | โœ… Yes | Your PayEz IDP client ID (string slug, e.g., `payez_idp_admin_web`) |
457
- | `IDP_URL` | โœ… Yes | PayEz IDP base URL (e.g., `https://idp.payez.net` or `http://localhost:32785`) |
458
- | `AUTH_TRUST_HOST` | โœ… Yes | Must be `true` - NextAuth derives OAuth URLs from request headers |
459
- | `NEXTAUTH_SECRET` | ๐Ÿ”„ Broker | **Do NOT set** - fetched automatically from IDP at startup (see below) |
460
- | `CLIENT_SECRET` | โš ๏ธ Legacy | Not needed with broker mode - IDP handles signing |
461
- | `NEXT_PUBLIC_IDP_BASE_URL` | โš ๏ธ Optional | Public-facing IDP URL (for client-side redirects) |
462
- | `REDIS_URL` | โš ๏ธ Optional | Redis connection string for session storage |
463
-
464
- ### NEXTAUTH_SECRET Broker Flow
465
-
466
- **The MVP uses a "broker" pattern for NEXTAUTH_SECRET** - the IDP securely provides it at startup rather than storing it in env files.
467
-
468
- ```
469
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
470
- โ”‚ App Startup (instrumentation.ts โ†’ ensureInitialized) โ”‚
471
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
472
- โ”‚
473
- โ–ผ
474
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
475
- โ”‚ Is NEXTAUTH_SECRET set and non-empty? โ”‚
476
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
477
- โ”‚ โ”‚
478
- YES NO (recommended)
479
- โ”‚ โ”‚
480
- โ–ผ โ–ผ
481
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
482
- โ”‚ Use as-is โ”‚ โ”‚ Fetch from IDP (Broker Mode) โ”‚
483
- โ”‚ (override) โ”‚ โ”‚ 1. Sign client assertion โ”‚
484
- โ”‚ โ”‚ โ”‚ 2. POST to /next-auth/secret โ”‚
485
- โ”‚ โ”‚ โ”‚ 3. Set process.env at runtime โ”‚
486
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
487
- ```
488
-
489
- **Key points:**
490
- - **Do NOT set `NEXTAUTH_SECRET` in `.env` files** - leave it undefined
491
- - The IDP provides the secret securely at startup via client assertion
492
- - Secret is cached for 5 minutes, then re-fetched if needed
493
- - If you DO set it manually, that value takes precedence (useful for overrides)
494
- - The broker needs `CLIENT_ID` and `IDP_URL` to fetch the secret
495
-
496
- ---
497
-
498
- ## Troubleshooting
499
-
500
- ### SessionProvider Error
501
-
502
- If you see `useSession must be wrapped in a <SessionProvider />`:
503
-
504
- 1. Ensure `transpilePackages: ['@payez/next-mvp']` is in `next.config.ts`
505
- 2. Make sure all page components using PayEz components have `'use client'` directive
506
- 3. Verify your app is wrapped with `<Providers>` in `layout.tsx`
507
-
508
- ### Module Resolution Errors
509
-
510
- If you get `Module not found` errors:
511
-
512
- 1. Clear Next.js cache: `rm -rf .next`
513
- 2. Reinstall dependencies: `npm install`
514
- 3. Restart dev server
515
-
516
- ### Authentication Not Working
517
-
518
- 1. Verify `CLIENT_ID` and `IDP_URL` are set correctly
519
- 2. Check `CLIENT_ID` matches your PayEz IDP configuration (use the slug, not numeric ID)
520
- 3. Verify IDP is running and reachable at `IDP_URL`
521
- 4. Check server logs for broker startup messages - look for "NEXTAUTH_SECRET Successfully Fetched from IDP"
522
- 5. If secret fetch fails, check IDP logs for client assertion errors
523
- 6. Check browser console for error messages
524
-
525
- ### NEXTAUTH_SECRET Issues
526
-
527
- **"NEXTAUTH_SECRET not available" error:**
528
- - This means the broker couldn't fetch the secret from IDP
529
- - Check that `IDP_URL` is correct and IDP is running
530
- - Verify `CLIENT_ID` is registered in the IDP
531
- - Check network connectivity between your app and IDP
532
-
533
- **Cookie cross-contamination (localhost development):**
534
- - If running multiple apps on localhost (different ports), NextAuth cookies can conflict
535
- - Clear `next-auth.*` cookies in browser, or use incognito
536
- - Each app uses a unique cookie name based on CLIENT_ID to avoid conflicts
537
-
538
- ---
539
-
540
- ## Docker/CI Deployment (IMPORTANT)
541
-
542
- When consuming `@payez/next-mvp` via a local `.tgz` file in Docker builds, you **must** use a local path reference.
543
-
544
- ### The Problem
545
-
546
- If your `package.json` references the MVP like this:
547
- ```json
548
- "@payez/next-mvp": "file:../PayEz-Next-MVP/packages/next-mvp/payez-next-mvp-2.6.50.tgz"
549
- ```
550
-
551
- Docker builds will **fail** with:
552
- ```
553
- npm error ENOENT: no such file or directory, open '/PayEz-Next-MVP/packages/next-mvp/payez-next-mvp-2.6.50.tgz'
554
- ```
555
-
556
- The relative path `../` resolves incorrectly inside the Docker container's `/app` working directory.
557
-
558
- ### The Fix
559
-
560
- 1. **Copy the `.tgz` file into your project root:**
561
- ```bash
562
- cp ../PayEz-Next-MVP/packages/next-mvp/payez-next-mvp-*.tgz ./
563
- ```
564
-
565
- 2. **Update `package.json` to use a local reference:**
566
- ```json
567
- "@payez/next-mvp": "file:./payez-next-mvp-2.6.50.tgz"
568
- ```
569
-
570
- 3. **Run `npm install` to update `package-lock.json`**
571
-
572
- 4. **Ensure your Dockerfile copies the tgz:**
573
- ```dockerfile
574
- COPY payez-next-mvp-*.tgz ./
575
- ```
576
-
577
- ### Quick Fix Script
578
-
579
- Run this in your consuming project to fix the path:
580
- ```bash
581
- # Copy latest tgz
582
- cp ../PayEz-Next-MVP/packages/next-mvp/payez-next-mvp-*.tgz ./
583
-
584
- # Update package.json path (adjust version as needed)
585
- sed -i 's|file:../PayEz-Next-MVP/packages/next-mvp/|file:./|g' package.json
586
-
587
- # Regenerate lockfile
588
- npm install --legacy-peer-deps
589
- ```
590
-
591
- ### After MVP Version Updates
592
-
593
- When you update the MVP package version, repeat steps 1-3 to copy the new `.tgz` and update references.
594
-
595
- ---
596
-
597
- ## Pre-Publishing Checklist (For Package Maintainers)
598
-
599
- Before publishing this package to npm:
600
-
601
- ### โœ… Code Quality
602
- - [x] All `@/` path aliases converted to relative paths
603
- - [x] TypeScript compiles without errors: `npm run build`
604
- - [x] No hardcoded configuration values (use env variables)
605
- - [ ] Unit tests pass (if implemented)
606
-
607
- ### ๐Ÿ“ฆ Package Configuration
608
-
609
- **CRITICAL FIXES NEEDED:**
610
-
611
- 1. **Fix `main` field in package.json (Line 5):**
612
- ```json
613
- "main": "dist/index.js", // NOT "src/index.ts"
614
- ```
615
-
616
- 2. **Remove unused `tsc-alias` from devDependencies (Line 542):**
617
- ```json
618
- // DELETE this line:
619
- "tsc-alias": "^1.8.16"
620
- ```
621
-
622
- 3. **Add package metadata:**
623
- ```json
624
- {
625
- "description": "PayEz IDP authentication package for Next.js with ready-to-use login, recovery, and profile pages",
626
- "keywords": ["nextjs", "authentication", "next-auth", "payez", "idp", "oauth"],
627
- "author": "PayEz Team",
628
- "license": "MIT",
629
- "repository": {
630
- "type": "git",
631
- "url": "https://github.com/your-org/PayEz-Next-MVP"
632
- },
633
- "homepage": "https://github.com/your-org/PayEz-Next-MVP#readme",
634
- "bugs": {
635
- "url": "https://github.com/your-org/PayEz-Next-MVP/issues"
636
- }
637
- }
638
- ```
639
-
640
- ### ๐Ÿ“ Documentation
641
- - [x] README.md is complete and accurate
642
- - [ ] CHANGELOG.md exists with version history
643
- - [ ] LICENSE file exists
644
-
645
- ### ๐Ÿงช Testing
646
- - [ ] Test fresh installation in new Next.js 14 project
647
- - [ ] Test fresh installation in new Next.js 15 project
648
- - [ ] Verify all exported modules work
649
- - [ ] Test with React 18 and React 19
650
- - [ ] Test package build: `npm pack --dry-run`
651
-
652
- ### ๐Ÿš€ Publishing Steps
653
-
654
- ```bash
655
- # 1. Fix package.json issues (see above)
656
-
657
- # 2. Login to npm
658
- npm login
659
-
660
- # 3. Build package
661
- npm run build
662
-
663
- # 4. Preview what will be published
664
- npm pack --dry-run
665
-
666
- # 5. Test the tarball locally
667
- npm install ./payez-next-mvp-2.3.1.tgz
668
-
669
- # 6. Bump version (patch/minor/major)
670
- npm version patch # 2.3.1 -> 2.3.2
671
- npm version minor # 2.3.1 -> 2.4.0
672
- npm version major # 2.3.1 -> 3.0.0
673
-
674
- # 7. Publish to npm
675
- npm publish
676
-
677
- # 8. Create git tag and push
678
- git push origin main
679
- git push origin --tags
680
- ```
681
-
682
- ### ๐Ÿ“‹ .npmignore
683
-
684
- Create `.npmignore` to exclude unnecessary files:
685
-
686
- ```
687
- src/
688
- *.test.ts
689
- *.test.tsx
690
- tsconfig.json
691
- .gitignore
692
- .git
693
- node_modules/
694
- *.tgz
695
- .env*
696
- ```
697
-
698
- ### ๐Ÿ”’ Publish Configuration
699
-
700
- Add to package.json:
701
-
702
- ```json
703
- "publishConfig": {
704
- "access": "public",
705
- "registry": "https://registry.npmjs.org/"
706
- }
707
- ```
708
-
709
- ---
710
-
711
- ## ๐Ÿ“š Complete Documentation
712
-
713
- ### Core Guides
714
-
715
- - **[THEMING.md](./docs/THEMING.md)** - Complete guide to customizing auth components
716
- - Theme structure and configuration
717
- - Creating light/dark modes
718
- - Component-specific customization
719
- - Common theming issues and solutions
720
-
721
- - **[CSS_VARIABLES_INTEGRATION.md](./docs/CSS_VARIABLES_INTEGRATION.md)** - CSS variable injection for MVP components
722
- - Why CSS variables are needed
723
- - How to inject variables in your app
724
- - Color conversion utilities
725
- - Debugging CSS variable issues
726
-
727
- - **[THEME_EXAMPLES.md](./docs/THEME_EXAMPLES.md)** - Ready-to-use theme examples
728
- - 7 pre-built professional themes
729
- - Multi-brand theme support
730
- - Dynamic light/dark mode
731
- - Copy-paste theme configurations
732
-
733
- ### Topics Covered
734
-
735
- #### Theming
736
- - โœ… Brand colors and logos
737
- - โœ… Light and dark modes
738
- - โœ… Font families and typography
739
- - โœ… Layout and spacing customization
740
- - โœ… Component-specific styling
741
- - โœ… Multi-tenant/white-label setups
742
- - โœ… Accessibility and contrast
743
-
744
- #### CSS Variables
745
- - โœ… Understanding CSS custom properties
746
- - โœ… Manual variable injection
747
- - โœ… Color conversion (Tailwind โ†’ hex)
748
- - โœ… Theme provider pattern
749
- - โœ… Dynamic theme switching
750
- - โœ… Debugging in DevTools
751
-
752
- #### Examples
753
- - โœ… Corporate themes
754
- - โœ… SaaS themes
755
- - โœ… Creative/design themes
756
- - โœ… Accessible high-contrast themes
757
- - โœ… Multi-brand configurations
758
- - โœ… Gradient backgrounds
759
- - โœ… Custom branding
760
-
761
- ### Quick Links
762
-
763
- **Getting Started with Themes:**
764
- 1. Start with [THEMING.md](./docs/THEMING.md) - Quick Start section
765
- 2. Copy a theme from [THEME_EXAMPLES.md](./docs/THEME_EXAMPLES.md)
766
- 3. Follow integration pattern in [CSS_VARIABLES_INTEGRATION.md](./docs/CSS_VARIABLES_INTEGRATION.md)
767
-
768
- **For Specific Tasks:**
769
- - Want to change colors? โ†’ [THEMING.md - Creating a Theme](./docs/THEMING.md#creating-a-theme)
770
- - Pages rendering white/no color? โ†’ [CSS_VARIABLES_INTEGRATION.md - Troubleshooting](./docs/CSS_VARIABLES_INTEGRATION.md#troubleshooting)
771
- - Need a complete example? โ†’ [THEME_EXAMPLES.md](./docs/THEME_EXAMPLES.md)
772
- - Debugging styling issues? โ†’ [THEMING.md - Common Issues](./docs/THEMING.md#common-issues--solutions)
773
-
774
- ---
775
-
776
- ## License
777
-
778
- MIT
779
-
780
- ## Support
781
-
782
- For issues and questions:
783
- - GitHub Issues: https://github.com/your-org/PayEz-Next-MVP/issues
784
- - Documentation: https://docs.payez.net
785
-
786
- ## Contributing
787
-
788
- Contributions welcome! Please read our contributing guidelines first.
789
-
790
- ---
791
-
792
- Made with โค๏ธ by the PayEz Team
1
+ # @payez/next-mvp
2
+
3
+ Drop-in authentication for Next.js. One package, zero secret management in production.
4
+
5
+ ```bash
6
+ npm install @payez/next-mvp next-auth
7
+ ```
8
+
9
+ ## How Secrets Work
10
+
11
+ You never manage signing keys or OAuth credentials directly. The package resolves them automatically at startup based on your environment.
12
+
13
+ | Environment | How it works | Secrets in your config? |
14
+ |-------------|-------------|------------------------|
15
+ | **Dev** | App calls IDP broker on your private network. One API key in `.env.local`. | One key (rotatable via CLI) |
16
+ | **Production** | App calls a cluster-internal endpoint. Network boundary = identity. | None |
17
+ | **Enterprise** | App uses an issued license key against your own or our IDP. | One key (rotatable via CLI) |
18
+
19
+ **In production, there are no secrets to configure, rotate, or leak.** The app proves its identity by being inside the cluster.
20
+
21
+ In dev, you have one key. Rotate it anytime:
22
+
23
+ ```bash
24
+ npx @payez/cli secret rotate
25
+ ```
26
+
27
+ Full architecture: [SECRET-MANAGEMENT-ARCHITECTURE.md](../../docs/SECRET-MANAGEMENT-ARCHITECTURE.md)
28
+
29
+ ## Features
30
+
31
+ - **Zero-secret production deployment** โ€” no signing keys, no OAuth secrets in your env
32
+ - **Complete authentication flow** โ€” login, logout, session management, password recovery
33
+ - **Pre-built UI components** โ€” themed login, recovery, and verify-code pages
34
+ - **Automatic token refresh** โ€” built-in refresh token handling with Redis session backing
35
+ - **Google OAuth + 2FA** โ€” pre-configured providers, MFA with email/SMS
36
+ - **Themeable** โ€” branding, colors, and layout via ThemeProvider
37
+ - **Next.js 14/15** โ€” App Router, React Server Components, middleware-ready
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ npm install @payez/next-mvp next-auth
43
+ # or
44
+ yarn add @payez/next-mvp next-auth
45
+ ```
46
+
47
+ ### Peer Dependencies
48
+
49
+ Ensure you have these installed:
50
+
51
+ ```bash
52
+ npm install next@^14.0.0 next-auth@^4.24.7 react@^18.2.0 react-dom@^18.2.0
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Development Scripts
58
+
59
+ PayEz MVP includes convenient development scripts for getting started quickly:
60
+
61
+ ### `npm run dev:local`
62
+
63
+ **Local Development Mode** - Perfect for first-time setup and testing without an external IDP:
64
+ - Auto-generates `NEXTAUTH_SECRET` for you
65
+ - No external IDP connection required
66
+ - Great for UI development and testing
67
+
68
+ ```bash
69
+ npm run dev:local
70
+ ```
71
+
72
+ This will:
73
+ 1. Generate a secure random `NEXTAUTH_SECRET`
74
+ 2. Display the secret (save it to your `.env.local`)
75
+ 3. Start the Next.js dev server on port 3000
76
+
77
+ ### `npm run dev:broker`
78
+
79
+ **Broker Mode** - Production-like authentication with PayEz IDP:
80
+ - Uses OAuth/OIDC flow with PayEz IDP
81
+ - Client assertion authentication
82
+ - Required for testing real authentication flows
83
+ - **This is a core feature for PayEz MVP users**
84
+
85
+ ```bash
86
+ npm run dev:broker
87
+ ```
88
+
89
+ This will:
90
+ 1. Enable broker mode (`USE_BROKER_MODE=true`)
91
+ 2. Set client ID for IDP authentication
92
+ 3. Start the Next.js dev server on port 3000
93
+ 4. Automatically kills any existing process on port 3000
94
+
95
+ **Custom Port & Client ID:**
96
+ ```bash
97
+ # In your consuming project's package.json
98
+ "scripts": {
99
+ "dev:broker": "pwsh -NoProfile -ExecutionPolicy Bypass -File node_modules/@payez/next-mvp/scripts/dev-broker.ps1 -ClientId 2 -Port 3400"
100
+ }
101
+ ```
102
+
103
+ ### Which Script to Use?
104
+
105
+ | Scenario | Script | When to Use |
106
+ |----------|--------|-------------|
107
+ | ๐ŸŽจ UI Development | `dev:local` | Building components, testing UI flows |
108
+ | ๐Ÿ” Auth Testing | `dev:broker` | Testing real OAuth flows, token management |
109
+ | ๐Ÿš€ Production-like | `dev:broker` | Testing with actual IDP integration |
110
+
111
+ ---
112
+
113
+ ## Quick Start (App Router with UI Components)
114
+
115
+ ### 1. Configure Next.js
116
+
117
+ Add to your `next.config.ts`:
118
+
119
+ ```typescript
120
+ import type { NextConfig } from "next";
121
+
122
+ const nextConfig: NextConfig = {
123
+ transpilePackages: ['@payez/next-mvp'],
124
+ };
125
+
126
+ export default nextConfig;
127
+ ```
128
+
129
+ ### 2. Set Environment Variables
130
+
131
+ Create `.env.local` (or `.env.development`) in your project root:
132
+
133
+ ```bash
134
+ # PayEz IDP Configuration (required)
135
+ CLIENT_ID=your_client_slug_from_payez # e.g., "payez_idp_admin_web"
136
+ IDP_URL=https://idp.payez.net # or http://localhost:32785 for local dev
137
+
138
+ # NextAuth trusts request headers for OAuth callback URLs
139
+ AUTH_TRUST_HOST=true
140
+
141
+ # NEXTAUTH_SECRET - DO NOT SET!
142
+ # The MVP broker fetches this securely from IDP at startup.
143
+ # Only set manually if you need to override the IDP-provided secret.
144
+
145
+ # Optional
146
+ REDIS_URL=redis://localhost:6379 # For session storage
147
+ NEXT_PUBLIC_IDP_BASE_URL=https://idp.payez.net # For client-side redirects
148
+ ```
149
+
150
+ > **Note:** `NEXTAUTH_SECRET` is intentionally omitted. The MVP automatically fetches it from the IDP at startup using the broker pattern. See [Environment Variables Reference](#environment-variables-reference) for details.
151
+
152
+ ### 3. Create NextAuth API Route
153
+
154
+ Create `app/api/auth/[...nextauth]/route.ts`:
155
+
156
+ ```typescript
157
+ /**
158
+ * NextAuth API Route Handler
159
+ * Uses pre-configured handler from @payez/next-mvp
160
+ */
161
+ export { GET, POST } from '@payez/next-mvp/routes/auth/nextauth';
162
+ ```
163
+
164
+ ### 4. Wrap Your App with Providers
165
+
166
+ Create `app/providers.tsx`:
167
+
168
+ ```typescript
169
+ 'use client';
170
+
171
+ import { SessionProvider } from 'next-auth/react';
172
+ import { ThemeProvider } from '@payez/next-mvp/theme';
173
+
174
+ export function Providers({ children }: { children: React.ReactNode }) {
175
+ return (
176
+ <SessionProvider>
177
+ <ThemeProvider>
178
+ {children}
179
+ </ThemeProvider>
180
+ </SessionProvider>
181
+ );
182
+ }
183
+ ```
184
+
185
+ Update `app/layout.tsx`:
186
+
187
+ ```typescript
188
+ import { Providers } from './providers';
189
+
190
+ export default function RootLayout({
191
+ children,
192
+ }: {
193
+ children: React.ReactNode;
194
+ }) {
195
+ return (
196
+ <html lang="en">
197
+ <body>
198
+ <Providers>
199
+ {children}
200
+ </Providers>
201
+ </body>
202
+ </html>
203
+ );
204
+ }
205
+ ```
206
+
207
+ ### 5. Add Authentication Pages
208
+
209
+ **Login Page** - `app/account-auth/login/page.tsx`:
210
+
211
+ ```typescript
212
+ 'use client';
213
+
214
+ import LoginPage from '@payez/next-mvp/dist/pages/login';
215
+
216
+ export default function LoginPageWrapper() {
217
+ return <LoginPage />;
218
+ }
219
+ ```
220
+
221
+ **Password Recovery** - `app/account-auth/recovery/page.tsx`:
222
+
223
+ ```typescript
224
+ 'use client';
225
+
226
+ import RecoveryPage from '@payez/next-mvp/dist/pages/recovery';
227
+
228
+ export default function RecoveryPageWrapper() {
229
+ return <RecoveryPage />;
230
+ }
231
+ ```
232
+
233
+ **Verify Code (2FA)** - `app/account-auth/verify-code/page.tsx`:
234
+
235
+ ```typescript
236
+ 'use client';
237
+
238
+ import VerifyCodePage from '@payez/next-mvp/dist/pages/verify-code';
239
+
240
+ export default function VerifyCodePageWrapper() {
241
+ return <VerifyCodePage />;
242
+ }
243
+ ```
244
+
245
+ ### 6. Protect Routes with Authentication
246
+
247
+ **Server-side protection:**
248
+
249
+ ```typescript
250
+ import { getServerSession } from 'next-auth';
251
+ import { redirect } from 'next/navigation';
252
+
253
+ export default async function DashboardPage() {
254
+ const session = await getServerSession();
255
+
256
+ if (!session) {
257
+ redirect('/account-auth/login');
258
+ }
259
+
260
+ return (
261
+ <div>
262
+ <h1>Welcome, {session.user?.email}</h1>
263
+ </div>
264
+ );
265
+ }
266
+ ```
267
+
268
+ **Client-side hook:**
269
+
270
+ ```typescript
271
+ 'use client';
272
+
273
+ import { useSession } from 'next-auth/react';
274
+
275
+ export default function ProfilePage() {
276
+ const { data: session, status } = useSession();
277
+
278
+ if (status === 'loading') return <div>Loading...</div>;
279
+ if (status === 'unauthenticated') return <div>Access Denied</div>;
280
+
281
+ return <div>Logged in as {session?.user?.email}</div>;
282
+ }
283
+ ```
284
+
285
+ ---
286
+
287
+ ## Advanced: V2 Middleware-Based Setup
288
+
289
+ For applications requiring middleware-based route protection:
290
+
291
+ ### 1. Configure Public Routes
292
+
293
+ Create `src/lib/auth.ts`:
294
+
295
+ ```typescript
296
+ import { configurePublicRoutes, createAuthOptions } from '@payez/next-mvp';
297
+ import CredentialsProvider from 'next-auth/providers/credentials';
298
+
299
+ // Define routes that do NOT require authentication
300
+ const publicRoutes = [
301
+ '/',
302
+ '/login',
303
+ '/api/health',
304
+ '/api/public/*', // Wildcard example
305
+ ];
306
+
307
+ configurePublicRoutes(publicRoutes);
308
+
309
+ export const authOptions = createAuthOptions({
310
+ credentialsProvider: CredentialsProvider,
311
+ // Additional NextAuthOptions can be passed here
312
+ });
313
+
314
+ export { authOptions as GET, authOptions as POST } from './auth';
315
+ ```
316
+
317
+ ### 2. Setup NextAuth API Route
318
+
319
+ **For Pages Router (`pages/api/auth/[...nextauth].ts`):**
320
+
321
+ ```typescript
322
+ import NextAuth from 'next-auth';
323
+ import { authOptions } from '../../../src/lib/auth';
324
+
325
+ export default NextAuth(authOptions);
326
+ ```
327
+
328
+ **For App Router (`app/api/auth/[...nextauth]/route.ts`):**
329
+
330
+ ```typescript
331
+ export { GET, POST } from '../../../src/lib/auth';
332
+ ```
333
+
334
+ ### 3. Implement Middleware
335
+
336
+ Create `middleware.ts` at project root:
337
+
338
+ ```typescript
339
+ import { createMvpMiddleware } from '@payez/next-mvp';
340
+
341
+ export default createMvpMiddleware();
342
+
343
+ export const config = {
344
+ matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
345
+ };
346
+ ```
347
+
348
+ ### 4. Use `fetchWithAuth` for Protected API Calls
349
+
350
+ ```typescript
351
+ import { fetchWithAuth } from '@payez/next-mvp';
352
+
353
+ async function fetchData() {
354
+ try {
355
+ const response = await fetchWithAuth('/api/protected-data');
356
+ const data = await response.json();
357
+ console.log(data);
358
+ } catch (error) {
359
+ console.error('Failed to fetch protected data:', error);
360
+ }
361
+ }
362
+ ```
363
+
364
+ ### 5. Session Viability API Handler
365
+
366
+ **For Pages Router (`pages/api/session/viability.ts`):**
367
+
368
+ ```typescript
369
+ import viabilityHandler from '@payez/next-mvp/api-handlers/session/viability';
370
+
371
+ export default viabilityHandler;
372
+ ```
373
+
374
+ **For App Router (`app/api/session/viability/route.ts`):**
375
+
376
+ ```typescript
377
+ export { default as GET } from '@payez/next-mvp/api-handlers/session/viability';
378
+ ```
379
+
380
+ ---
381
+
382
+ ## Custom Theming
383
+
384
+ Customize branding and colors:
385
+
386
+ ```typescript
387
+ // lib/mvp-theme-config.ts
388
+ import { ThemeConfig } from '@payez/next-mvp/theme';
389
+
390
+ const customTheme: ThemeConfig = {
391
+ branding: {
392
+ companyName: "Your Company",
393
+ logoUrl: "/logo.svg",
394
+ logoAlt: "Your Company Logo"
395
+ },
396
+ colors: {
397
+ primary: "#3b82f6", // Blue
398
+ primaryHover: "#2563eb",
399
+ secondary: "#10b981", // Green
400
+ danger: "#ef4444", // Red
401
+ text: "#1f2937",
402
+ textLight: "#6b7280",
403
+ background: "#ffffff",
404
+ backgroundAlt: "#f9fafb",
405
+ border: "#e5e7eb"
406
+ },
407
+ layout: {
408
+ maxWidth: "28rem", // max-w-md
409
+ padding: "1.5rem", // p-6
410
+ borderRadius: "0.5rem" // rounded-lg
411
+ }
412
+ };
413
+
414
+ export default customTheme;
415
+ ```
416
+
417
+ Then use in your Providers:
418
+
419
+ ```typescript
420
+ import customTheme from '@/lib/mvp-theme-config';
421
+
422
+ export function Providers({ children }: { children: React.ReactNode }) {
423
+ return (
424
+ <SessionProvider>
425
+ <ThemeProvider theme={customTheme}>
426
+ {children}
427
+ </ThemeProvider>
428
+ </SessionProvider>
429
+ );
430
+ }
431
+ ```
432
+
433
+ ---
434
+
435
+ ## API Routes
436
+
437
+ Access pre-built API handlers:
438
+
439
+ ```typescript
440
+ // Session validation
441
+ import { GET as validateSession } from '@payez/next-mvp/routes/auth/session';
442
+
443
+ // Token refresh
444
+ import { POST as refreshToken } from '@payez/next-mvp/routes/auth/refresh';
445
+
446
+ // Logout
447
+ import { POST as logout } from '@payez/next-mvp/routes/auth/logout';
448
+ ```
449
+
450
+ ---
451
+
452
+ ## Environment Variables Reference
453
+
454
+ | Variable | Required | Description |
455
+ |----------|----------|-------------|
456
+ | `CLIENT_ID` | โœ… Yes | Your PayEz IDP client ID (string slug, e.g., `payez_idp_admin_web`) |
457
+ | `IDP_URL` | โœ… Yes | PayEz IDP base URL (e.g., `https://idp.payez.net` or `http://localhost:32785`) |
458
+ | `AUTH_TRUST_HOST` | โœ… Yes | Must be `true` - NextAuth derives OAuth URLs from request headers |
459
+ | `NEXTAUTH_SECRET` | ๐Ÿ”„ Broker | **Do NOT set** - fetched automatically from IDP at startup (see below) |
460
+ | `CLIENT_SECRET` | โš ๏ธ Legacy | Not needed with broker mode - IDP handles signing |
461
+ | `NEXT_PUBLIC_IDP_BASE_URL` | โš ๏ธ Optional | Public-facing IDP URL (for client-side redirects) |
462
+ | `REDIS_URL` | โš ๏ธ Optional | Redis connection string for session storage |
463
+
464
+ ### NEXTAUTH_SECRET Broker Flow
465
+
466
+ **The MVP uses a "broker" pattern for NEXTAUTH_SECRET** - the IDP securely provides it at startup rather than storing it in env files.
467
+
468
+ ```
469
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
470
+ โ”‚ App Startup (instrumentation.ts โ†’ ensureInitialized) โ”‚
471
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
472
+ โ”‚
473
+ โ–ผ
474
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
475
+ โ”‚ Is NEXTAUTH_SECRET set and non-empty? โ”‚
476
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
477
+ โ”‚ โ”‚
478
+ YES NO (recommended)
479
+ โ”‚ โ”‚
480
+ โ–ผ โ–ผ
481
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
482
+ โ”‚ Use as-is โ”‚ โ”‚ Fetch from IDP (Broker Mode) โ”‚
483
+ โ”‚ (override) โ”‚ โ”‚ 1. Sign client assertion โ”‚
484
+ โ”‚ โ”‚ โ”‚ 2. POST to /next-auth/secret โ”‚
485
+ โ”‚ โ”‚ โ”‚ 3. Set process.env at runtime โ”‚
486
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
487
+ ```
488
+
489
+ **Key points:**
490
+ - **Do NOT set `NEXTAUTH_SECRET` in `.env` files** - leave it undefined
491
+ - The IDP provides the secret securely at startup via client assertion
492
+ - Secret is cached for 5 minutes, then re-fetched if needed
493
+ - If you DO set it manually, that value takes precedence (useful for overrides)
494
+ - The broker needs `CLIENT_ID` and `IDP_URL` to fetch the secret
495
+
496
+ ---
497
+
498
+ ## Troubleshooting
499
+
500
+ ### SessionProvider Error
501
+
502
+ If you see `useSession must be wrapped in a <SessionProvider />`:
503
+
504
+ 1. Ensure `transpilePackages: ['@payez/next-mvp']` is in `next.config.ts`
505
+ 2. Make sure all page components using PayEz components have `'use client'` directive
506
+ 3. Verify your app is wrapped with `<Providers>` in `layout.tsx`
507
+
508
+ ### Module Resolution Errors
509
+
510
+ If you get `Module not found` errors:
511
+
512
+ 1. Clear Next.js cache: `rm -rf .next`
513
+ 2. Reinstall dependencies: `npm install`
514
+ 3. Restart dev server
515
+
516
+ ### Authentication Not Working
517
+
518
+ 1. Verify `CLIENT_ID` and `IDP_URL` are set correctly
519
+ 2. Check `CLIENT_ID` matches your PayEz IDP configuration (use the slug, not numeric ID)
520
+ 3. Verify IDP is running and reachable at `IDP_URL`
521
+ 4. Check server logs for broker startup messages - look for "NEXTAUTH_SECRET Successfully Fetched from IDP"
522
+ 5. If secret fetch fails, check IDP logs for client assertion errors
523
+ 6. Check browser console for error messages
524
+
525
+ ### NEXTAUTH_SECRET Issues
526
+
527
+ **"NEXTAUTH_SECRET not available" error:**
528
+ - This means the broker couldn't fetch the secret from IDP
529
+ - Check that `IDP_URL` is correct and IDP is running
530
+ - Verify `CLIENT_ID` is registered in the IDP
531
+ - Check network connectivity between your app and IDP
532
+
533
+ **Cookie cross-contamination (localhost development):**
534
+ - If running multiple apps on localhost (different ports), NextAuth cookies can conflict
535
+ - Clear `next-auth.*` cookies in browser, or use incognito
536
+ - Each app uses a unique cookie name based on CLIENT_ID to avoid conflicts
537
+
538
+ ---
539
+
540
+ ## Docker/CI Deployment (IMPORTANT)
541
+
542
+ When consuming `@payez/next-mvp` via a local `.tgz` file in Docker builds, you **must** use a local path reference.
543
+
544
+ ### The Problem
545
+
546
+ If your `package.json` references the MVP like this:
547
+ ```json
548
+ "@payez/next-mvp": "file:../PayEz-Next-MVP/packages/next-mvp/payez-next-mvp-2.6.50.tgz"
549
+ ```
550
+
551
+ Docker builds will **fail** with:
552
+ ```
553
+ npm error ENOENT: no such file or directory, open '/PayEz-Next-MVP/packages/next-mvp/payez-next-mvp-2.6.50.tgz'
554
+ ```
555
+
556
+ The relative path `../` resolves incorrectly inside the Docker container's `/app` working directory.
557
+
558
+ ### The Fix
559
+
560
+ 1. **Copy the `.tgz` file into your project root:**
561
+ ```bash
562
+ cp ../PayEz-Next-MVP/packages/next-mvp/payez-next-mvp-*.tgz ./
563
+ ```
564
+
565
+ 2. **Update `package.json` to use a local reference:**
566
+ ```json
567
+ "@payez/next-mvp": "file:./payez-next-mvp-2.6.50.tgz"
568
+ ```
569
+
570
+ 3. **Run `npm install` to update `package-lock.json`**
571
+
572
+ 4. **Ensure your Dockerfile copies the tgz:**
573
+ ```dockerfile
574
+ COPY payez-next-mvp-*.tgz ./
575
+ ```
576
+
577
+ ### Quick Fix Script
578
+
579
+ Run this in your consuming project to fix the path:
580
+ ```bash
581
+ # Copy latest tgz
582
+ cp ../PayEz-Next-MVP/packages/next-mvp/payez-next-mvp-*.tgz ./
583
+
584
+ # Update package.json path (adjust version as needed)
585
+ sed -i 's|file:../PayEz-Next-MVP/packages/next-mvp/|file:./|g' package.json
586
+
587
+ # Regenerate lockfile
588
+ npm install --legacy-peer-deps
589
+ ```
590
+
591
+ ### After MVP Version Updates
592
+
593
+ When you update the MVP package version, repeat steps 1-3 to copy the new `.tgz` and update references.
594
+
595
+ ---
596
+
597
+ ## Pre-Publishing Checklist (For Package Maintainers)
598
+
599
+ Before publishing this package to npm:
600
+
601
+ ### โœ… Code Quality
602
+ - [x] All `@/` path aliases converted to relative paths
603
+ - [x] TypeScript compiles without errors: `npm run build`
604
+ - [x] No hardcoded configuration values (use env variables)
605
+ - [ ] Unit tests pass (if implemented)
606
+
607
+ ### ๐Ÿ“ฆ Package Configuration
608
+
609
+ **CRITICAL FIXES NEEDED:**
610
+
611
+ 1. **Fix `main` field in package.json (Line 5):**
612
+ ```json
613
+ "main": "dist/index.js", // NOT "src/index.ts"
614
+ ```
615
+
616
+ 2. **Remove unused `tsc-alias` from devDependencies (Line 542):**
617
+ ```json
618
+ // DELETE this line:
619
+ "tsc-alias": "^1.8.16"
620
+ ```
621
+
622
+ 3. **Add package metadata:**
623
+ ```json
624
+ {
625
+ "description": "PayEz IDP authentication package for Next.js with ready-to-use login, recovery, and profile pages",
626
+ "keywords": ["nextjs", "authentication", "next-auth", "payez", "idp", "oauth"],
627
+ "author": "PayEz Team",
628
+ "license": "MIT",
629
+ "repository": {
630
+ "type": "git",
631
+ "url": "https://github.com/your-org/PayEz-Next-MVP"
632
+ },
633
+ "homepage": "https://github.com/your-org/PayEz-Next-MVP#readme",
634
+ "bugs": {
635
+ "url": "https://github.com/your-org/PayEz-Next-MVP/issues"
636
+ }
637
+ }
638
+ ```
639
+
640
+ ### ๐Ÿ“ Documentation
641
+ - [x] README.md is complete and accurate
642
+ - [ ] CHANGELOG.md exists with version history
643
+ - [ ] LICENSE file exists
644
+
645
+ ### ๐Ÿงช Testing
646
+ - [ ] Test fresh installation in new Next.js 14 project
647
+ - [ ] Test fresh installation in new Next.js 15 project
648
+ - [ ] Verify all exported modules work
649
+ - [ ] Test with React 18 and React 19
650
+ - [ ] Test package build: `npm pack --dry-run`
651
+
652
+ ### ๐Ÿš€ Publishing Steps
653
+
654
+ ```bash
655
+ # 1. Fix package.json issues (see above)
656
+
657
+ # 2. Login to npm
658
+ npm login
659
+
660
+ # 3. Build package
661
+ npm run build
662
+
663
+ # 4. Preview what will be published
664
+ npm pack --dry-run
665
+
666
+ # 5. Test the tarball locally
667
+ npm install ./payez-next-mvp-2.3.1.tgz
668
+
669
+ # 6. Bump version (patch/minor/major)
670
+ npm version patch # 2.3.1 -> 2.3.2
671
+ npm version minor # 2.3.1 -> 2.4.0
672
+ npm version major # 2.3.1 -> 3.0.0
673
+
674
+ # 7. Publish to npm
675
+ npm publish
676
+
677
+ # 8. Create git tag and push
678
+ git push origin main
679
+ git push origin --tags
680
+ ```
681
+
682
+ ### ๐Ÿ“‹ .npmignore
683
+
684
+ Create `.npmignore` to exclude unnecessary files:
685
+
686
+ ```
687
+ src/
688
+ *.test.ts
689
+ *.test.tsx
690
+ tsconfig.json
691
+ .gitignore
692
+ .git
693
+ node_modules/
694
+ *.tgz
695
+ .env*
696
+ ```
697
+
698
+ ### ๐Ÿ”’ Publish Configuration
699
+
700
+ Add to package.json:
701
+
702
+ ```json
703
+ "publishConfig": {
704
+ "access": "public",
705
+ "registry": "https://registry.npmjs.org/"
706
+ }
707
+ ```
708
+
709
+ ---
710
+
711
+ ## ๐Ÿ“š Complete Documentation
712
+
713
+ ### Core Guides
714
+
715
+ - **[THEMING.md](./docs/THEMING.md)** - Complete guide to customizing auth components
716
+ - Theme structure and configuration
717
+ - Creating light/dark modes
718
+ - Component-specific customization
719
+ - Common theming issues and solutions
720
+
721
+ - **[CSS_VARIABLES_INTEGRATION.md](./docs/CSS_VARIABLES_INTEGRATION.md)** - CSS variable injection for MVP components
722
+ - Why CSS variables are needed
723
+ - How to inject variables in your app
724
+ - Color conversion utilities
725
+ - Debugging CSS variable issues
726
+
727
+ - **[THEME_EXAMPLES.md](./docs/THEME_EXAMPLES.md)** - Ready-to-use theme examples
728
+ - 7 pre-built professional themes
729
+ - Multi-brand theme support
730
+ - Dynamic light/dark mode
731
+ - Copy-paste theme configurations
732
+
733
+ ### Topics Covered
734
+
735
+ #### Theming
736
+ - โœ… Brand colors and logos
737
+ - โœ… Light and dark modes
738
+ - โœ… Font families and typography
739
+ - โœ… Layout and spacing customization
740
+ - โœ… Component-specific styling
741
+ - โœ… Multi-tenant/white-label setups
742
+ - โœ… Accessibility and contrast
743
+
744
+ #### CSS Variables
745
+ - โœ… Understanding CSS custom properties
746
+ - โœ… Manual variable injection
747
+ - โœ… Color conversion (Tailwind โ†’ hex)
748
+ - โœ… Theme provider pattern
749
+ - โœ… Dynamic theme switching
750
+ - โœ… Debugging in DevTools
751
+
752
+ #### Examples
753
+ - โœ… Corporate themes
754
+ - โœ… SaaS themes
755
+ - โœ… Creative/design themes
756
+ - โœ… Accessible high-contrast themes
757
+ - โœ… Multi-brand configurations
758
+ - โœ… Gradient backgrounds
759
+ - โœ… Custom branding
760
+
761
+ ### Quick Links
762
+
763
+ **Getting Started with Themes:**
764
+ 1. Start with [THEMING.md](./docs/THEMING.md) - Quick Start section
765
+ 2. Copy a theme from [THEME_EXAMPLES.md](./docs/THEME_EXAMPLES.md)
766
+ 3. Follow integration pattern in [CSS_VARIABLES_INTEGRATION.md](./docs/CSS_VARIABLES_INTEGRATION.md)
767
+
768
+ **For Specific Tasks:**
769
+ - Want to change colors? โ†’ [THEMING.md - Creating a Theme](./docs/THEMING.md#creating-a-theme)
770
+ - Pages rendering white/no color? โ†’ [CSS_VARIABLES_INTEGRATION.md - Troubleshooting](./docs/CSS_VARIABLES_INTEGRATION.md#troubleshooting)
771
+ - Need a complete example? โ†’ [THEME_EXAMPLES.md](./docs/THEME_EXAMPLES.md)
772
+ - Debugging styling issues? โ†’ [THEMING.md - Common Issues](./docs/THEMING.md#common-issues--solutions)
773
+
774
+ ---
775
+
776
+ ## License
777
+
778
+ MIT
779
+
780
+ ## Support
781
+
782
+ For issues and questions:
783
+ - GitHub Issues: https://github.com/your-org/PayEz-Next-MVP/issues
784
+ - Documentation: https://docs.payez.net
785
+
786
+ ## Contributing
787
+
788
+ Contributions welcome! Please read our contributing guidelines first.
789
+
790
+ ---
791
+
792
+ Made with โค๏ธ by the PayEz Team