@main12/auth-login 0.2.3 → 0.3.1

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.
package/README.md CHANGED
@@ -10,8 +10,9 @@ plugins: [
10
10
  authLoginPlugin({
11
11
  projectName: 'My SaaS',
12
12
  domain: 'https://myapp.com',
13
- logo: 'https://myapp.com/logo.png', // shown in all auth pages + emails
14
- style: 'hero-ui', // 'tailwind' (default) | 'hero-ui'
13
+ logo: 'https://myapp.com/logo.png',
14
+ style: 'tailwind',
15
+ routeRedirects: true,
15
16
  }),
16
17
  ]
17
18
  ```
@@ -21,7 +22,10 @@ plugins: [
21
22
  ## Features
22
23
 
23
24
  - **5 auth pages** — login (multi-step), signup, forgot password, verify OTP, set password
25
+ - **Single catch-all route** — one file handles all auth pages (`AuthPages` component)
26
+ - **Route redirects** — automatic `/login` → `/auth/login`, `/admin/login` → `/auth/login` via Next.js 16 proxy
24
27
  - **Multi-style** — `tailwind` (zero UI deps) or `hero-ui` (HeroUI + framer-motion). Set once in config
28
+ - **Google OAuth** — optional, enable via `providers` config (hidden by default)
25
29
  - **5 API endpoints** — `check-email`, `otp/send`, `otp/verify`, `set-password`, `signup`
26
30
  - **OTP engine** — SHA-256 hashing + `timingSafeEqual` comparison, 10-min expiry, 3 attempts
27
31
  - **Email templates** — welcome, OTP login, password reset, password changed (EN/ES)
@@ -49,11 +53,14 @@ pnpm add @heroui/react framer-motion @iconify/react
49
53
 
50
54
  ---
51
55
 
52
- ## Quick Start
56
+ ## Quick Start (Simplified Setup)
57
+
58
+ The fastest way to get all auth pages running with just **2 files**.
53
59
 
54
60
  ### 1. Add the plugin + Users collection
55
61
 
56
62
  ```ts
63
+ // payload.config.ts
57
64
  import { authLoginPlugin } from '@main12/auth-login'
58
65
 
59
66
  export default buildConfig({
@@ -74,45 +81,50 @@ export default buildConfig({
74
81
  projectName: 'My App',
75
82
  domain: 'https://myapp.com',
76
83
  logo: '/logo.png',
77
- style: 'hero-ui',
84
+ style: 'tailwind',
85
+ routeRedirects: true, // enables /login → /auth/login redirects
78
86
  }),
79
87
  ],
80
88
  })
81
89
  ```
82
90
 
83
- ### 2. Create one-line route files
91
+ ### 2. Create the catch-all auth route (1 file)
84
92
 
85
93
  ```tsx
86
- // src/app/(frontend)/(auth)/login/page.tsx
87
- export { LoginPage as default } from '@main12/auth-login/client'
88
-
89
- // src/app/(frontend)/(auth)/signup/page.tsx
90
- export { SignupPage as default } from '@main12/auth-login/client'
91
-
92
- // src/app/(frontend)/(auth)/forgot-password/page.tsx
93
- export { ForgotPasswordPage as default } from '@main12/auth-login/client'
94
+ // src/app/(frontend)/(auth)/auth/[...slug]/page.tsx
95
+ 'use client'
94
96
 
95
- // src/app/(frontend)/(auth)/verify-otp/page.tsx
96
- export { VerifyOtpPage as default } from '@main12/auth-login/client'
97
+ import { use } from 'react'
98
+ import { AuthPages } from '@main12/auth-login/client'
97
99
 
98
- // src/app/(frontend)/(auth)/set-password/page.tsx
99
- export { SetPasswordPage as default } from '@main12/auth-login/client'
100
+ export default function Page({ params }: { params: Promise<{ slug: string[] }> }) {
101
+ const { slug } = use(params)
102
+ return <AuthPages slug={slug} />
103
+ }
100
104
  ```
101
105
 
102
- ### 3. Wire up the login action
106
+ This single file handles all routes:
107
+ - `/auth/login`
108
+ - `/auth/signup`
109
+ - `/auth/forgot-password`
110
+ - `/auth/verify-otp`
111
+ - `/auth/set-password`
103
112
 
104
- ```tsx
105
- // login/page.tsx
106
- 'use client'
107
- import { LoginPage } from '@main12/auth-login/client'
108
- import { useAuth } from '@/providers/Auth'
113
+ ### 3. Add the proxy for route redirects (1 file)
109
114
 
110
- export default function Page() {
111
- const { login } = useAuth()
112
- return <LoginPage onPasswordLogin={login} redirectTo="/dashboard" />
113
- }
115
+ ```ts
116
+ // src/proxy.ts (Next.js 16+)
117
+ export { proxy, config } from '@main12/auth-login/proxy'
114
118
  ```
115
119
 
120
+ This redirects:
121
+ - `/login` → `/auth/login`
122
+ - `/signup` → `/auth/signup`
123
+ - `/forgot-password` → `/auth/forgot-password`
124
+ - `/verify-otp` → `/auth/verify-otp`
125
+ - `/set-password` → `/auth/set-password`
126
+ - `/admin/login` → `/auth/login` (**always**, regardless of `routeRedirects` setting)
127
+
116
128
  ### 4. Visit `/login` — done.
117
129
 
118
130
  ---
@@ -121,26 +133,127 @@ export default function Page() {
121
133
 
122
134
  ```ts
123
135
  authLoginPlugin({
136
+ // Core
124
137
  projectName: 'My App', // Email subjects + footers
125
138
  contactEmail: 'hi@myapp.com', // Email footer contact
126
139
  domain: 'https://myapp.com', // Links in emails
127
140
  logo: '/logo.png', // All auth pages + email headers
128
141
  style: 'tailwind', // 'tailwind' | 'hero-ui'
129
142
  enabled: true,
143
+
144
+ // Route redirects
145
+ routeRedirects: true, // Enable /login → /auth/login redirects
146
+ // or with custom base path:
147
+ // routeRedirects: { basePath: '/auth' },
148
+
149
+ // OAuth providers (optional — hidden by default)
150
+ providers: {
151
+ google: {
152
+ clientId: process.env.GOOGLE_CLIENT_ID,
153
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET,
154
+ },
155
+ },
156
+ })
157
+ ```
158
+
159
+ ### Route Redirects
160
+
161
+ | Value | Behavior |
162
+ |-------|----------|
163
+ | `false` (default) | No redirects. You manage your own routes. |
164
+ | `true` | Redirects `/login`, `/signup`, etc. → `/auth/login`, `/auth/signup`, etc. |
165
+ | `{ basePath: '/myauth' }` | Same, but redirects to `/myauth/login`, etc. |
166
+
167
+ > **Note:** `/admin/login` is **always** redirected to the plugin login page when the proxy is active, regardless of the `routeRedirects` setting.
168
+
169
+ ### Google OAuth (Providers)
170
+
171
+ Google OAuth is **hidden by default**. To enable it, just add `providers.google` — the plugin handles everything (UI buttons + server-side OAuth flow via `payload-oauth2` under the hood):
172
+
173
+ ```ts
174
+ authLoginPlugin({
175
+ providers: {
176
+ google: {
177
+ clientId: process.env.GOOGLE_CLIENT_ID,
178
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET,
179
+ successRedirect: '/dashboard', // optional, defaults to '/admin'
180
+ failureRedirect: '/login?error=failed', // optional
181
+ },
182
+ },
130
183
  })
131
184
  ```
132
185
 
186
+ That's it. No extra packages to install, no extra plugins to configure.
187
+
188
+ | Config | Behavior |
189
+ |--------|----------|
190
+ | Omitted / not set | Google OAuth hidden |
191
+ | `google: true` | Auto-detect `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` from env |
192
+ | `google: { clientId, clientSecret }` | Enable with explicit credentials |
193
+ | `google: false` | Force disable |
194
+
195
+ ---
196
+
197
+ ## AuthPages Props
198
+
199
+ The `AuthPages` component accepts these props for customization:
200
+
201
+ ```tsx
202
+ <AuthPages
203
+ slug={slug} // Required — from catch-all route params
204
+ redirectTo="/dashboard" // Where to go after login/set-password (default: '/admin')
205
+ logo={<MyLogo />} // Custom logo component
206
+ basePath="/auth" // Base path for sibling links (default: '/auth')
207
+ showGoogleOAuth={true} // Override Google OAuth visibility
208
+ onPasswordLogin={customLogin} // Custom login handler
209
+ onSignup={customSignup} // Custom signup handler
210
+ />
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Individual Page Setup (Advanced)
216
+
217
+ If you need full control over each page, create separate route files instead of using `AuthPages`:
218
+
219
+ ```tsx
220
+ // login/page.tsx
221
+ 'use client'
222
+ import { LoginPage } from '@main12/auth-login/client'
223
+
224
+ export default function Page() {
225
+ return (
226
+ <LoginPage
227
+ onPasswordLogin={async ({ email, password }) => {
228
+ const res = await fetch('/api/users/login', {
229
+ method: 'POST',
230
+ headers: { 'Content-Type': 'application/json' },
231
+ body: JSON.stringify({ email, password }),
232
+ })
233
+ if (!res.ok) throw new Error('Login failed')
234
+ }}
235
+ redirectTo="/dashboard"
236
+ signupUrl="/signup"
237
+ />
238
+ )
239
+ }
240
+ ```
241
+
133
242
  ### Per-page overrides
134
243
 
135
244
  ```tsx
136
245
  <LoginPage
137
- logo={<AppLogo width={180} />} // Override global logo (optional)
138
- onPasswordLogin={login} // Required
246
+ logo={<AppLogo width={180} />}
247
+ onPasswordLogin={login}
139
248
  redirectTo="/dashboard"
140
249
  showGoogleOAuth={true}
141
250
  signupUrl="/signup"
142
- poweredBy={{ enabled: true, logoUrl: '/custom.png', linkUrl: 'https://...' }}
143
251
  />
252
+
253
+ <SignupPage onSignup={signup} loginUrl="/login" />
254
+ <ForgotPasswordPage loginUrl="/login" />
255
+ <VerifyOtpPage loginUrl="/login" />
256
+ <SetPasswordPage redirectTo="/dashboard" />
144
257
  ```
145
258
 
146
259
  ---
@@ -289,17 +402,39 @@ await payload.sendEmail({
289
402
 
290
403
  ---
291
404
 
405
+ ## Exports
406
+
407
+ | Import path | Contents |
408
+ |-------------|----------|
409
+ | `@main12/auth-login` | Plugin factory, types, server config |
410
+ | `@main12/auth-login/client` | Page components, `AuthPages`, hooks, services, UI utilities |
411
+ | `@main12/auth-login/rsc` | Email template generators, translations |
412
+ | `@main12/auth-login/proxy` | Next.js 16 proxy for route redirects |
413
+
414
+ ---
415
+
292
416
  ## ShadCN Compatibility
293
417
 
294
418
  The `tailwind` style works in ShadCN projects out of the box. For ShadCN components, build a [custom page](#building-custom-pages) — import the plugin's hooks and use your `@/components/ui/button`, `@/components/ui/input`, etc.
295
419
 
296
420
  ---
297
421
 
422
+ ## Setup Comparison
423
+
424
+ | Approach | Files needed | Best for |
425
+ |----------|-------------|----------|
426
+ | **Catch-all + proxy** (recommended) | 2 files | Most projects — fastest setup |
427
+ | **Individual pages** | 5 files | Full control over each page |
428
+ | **Custom pages with hooks** | Your own files | Completely custom UI |
429
+ | **Backend only** (`routeRedirects: false`, no `AuthPages`) | 0 frontend files | Custom frontend using only the API endpoints + hooks |
430
+
431
+ ---
432
+
298
433
  ## 🤖 AI Agent Prompts
299
434
 
300
435
  Copy these prompts into Claude, Cursor, Copilot, or any AI agent.
301
436
 
302
- ### Prompt: Set up the auth plugin in a new Payload project
437
+ ### Prompt: Set up the auth plugin (simplified catch-all)
303
438
 
304
439
  ```
305
440
  Add @main12/auth-login to this Payload project:
@@ -307,15 +442,38 @@ Add @main12/auth-login to this Payload project:
307
442
  1. Install: pnpm add @main12/auth-login
308
443
  2. In payload.config.ts, add:
309
444
  - Users collection with auth enabled + otpHash, otpAttempts, otpExpiresAt fields
310
- - Plugin: authLoginPlugin({ projectName: "<PROJECT>", domain: "<URL>", logo: "/logo.png", style: "hero-ui" })
311
- 3. Create route files under src/app/(frontend)/(auth)/:
312
- - login/page.tsx → export { LoginPage as default } from '@main12/auth-login/client'
313
- - signup/page.tsx → export { SignupPage as default } from '@main12/auth-login/client'
314
- - forgot-password/page.tsx → export { ForgotPasswordPage as default } from '@main12/auth-login/client'
315
- - verify-otp/page.tsx → export { VerifyOtpPage as default } from '@main12/auth-login/client'
316
- - set-password/page.tsx → export { SetPasswordPage as default } from '@main12/auth-login/client'
317
- 4. In login/page.tsx, wrap LoginPage with useAuth() to pass onPasswordLogin={login}.
318
- 5. Verify: visit /login
445
+ - Plugin: authLoginPlugin({ projectName: "<PROJECT>", domain: "<URL>", logo: "/logo.png", style: "tailwind", routeRedirects: true })
446
+ 3. Create catch-all route: src/app/(frontend)/(auth)/auth/[...slug]/page.tsx
447
+ - 'use client', import { use } from 'react', import { AuthPages } from '@main12/auth-login/client'
448
+ - export default function Page({ params }) { const { slug } = use(params); return <AuthPages slug={slug} /> }
449
+ 4. Create proxy: src/proxy.ts
450
+ - export { proxy, config } from '@main12/auth-login/proxy'
451
+ 5. Verify: visit /login → should redirect to /auth/login
452
+ ```
453
+
454
+ ### Prompt: Set up with Google OAuth
455
+
456
+ ```
457
+ Add @main12/auth-login with Google OAuth to this Payload project:
458
+
459
+ 1. Install: pnpm add @main12/auth-login
460
+ 2. In payload.config.ts, add:
461
+ - Users collection with auth enabled + otpHash, otpAttempts, otpExpiresAt fields
462
+ - Plugin: authLoginPlugin({
463
+ projectName: "<PROJECT>",
464
+ domain: "<URL>",
465
+ style: "tailwind",
466
+ routeRedirects: true,
467
+ providers: {
468
+ google: {
469
+ clientId: process.env.GOOGLE_CLIENT_ID,
470
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET,
471
+ }
472
+ }
473
+ })
474
+ 3. Create catch-all route + proxy (same as simplified setup)
475
+ 4. Add GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to .env
476
+ 5. Verify: visit /login → should show Google OAuth button
319
477
  ```
320
478
 
321
479
  ### Prompt: Build a custom login page with HeroUI components
@@ -2,6 +2,7 @@
2
2
  import { useState, useCallback } from 'react';
3
3
  import { useRouter } from 'next/navigation';
4
4
  import { checkEmail, sendOtp, initiateGoogleLogin } from '../services/authService.js';
5
+ import { pluginConfig } from '../../../config.js';
5
6
  /**
6
7
  * State machine for the multi-step login flow: email → password | otp-prompt.
7
8
  * The page component owns the UI; this hook owns the logic.
@@ -25,14 +26,29 @@ import { checkEmail, sendOtp, initiateGoogleLogin } from '../services/authServic
25
26
  setError('noAccountFound');
26
27
  return;
27
28
  }
28
- setStep(data.hasPassword ? 'password' : 'otp-prompt');
29
+ const { passwordLogin: passwordLoginEnabled, otpLogin: otpLoginEnabled } = pluginConfig;
30
+ if (data.hasPassword && passwordLoginEnabled) {
31
+ // Show password step if user has a password and password login is enabled
32
+ setStep('password');
33
+ return;
34
+ }
35
+ // OTP login — send OTP immediately and redirect to verify page
36
+ const otpData = await sendOtp(email, 'login');
37
+ if (otpData.success) {
38
+ const redirectParam = redirectTo !== '/' ? `&redirect=${encodeURIComponent(redirectTo)}` : '';
39
+ router.push(`/verify-otp?email=${encodeURIComponent(email.trim())}${redirectParam}`);
40
+ } else {
41
+ setError(otpData.message || 'otpSendFailed');
42
+ }
29
43
  } catch {
30
44
  setError('genericError');
31
45
  } finally{
32
46
  setIsLoading(false);
33
47
  }
34
48
  }, [
35
- email
49
+ email,
50
+ redirectTo,
51
+ router
36
52
  ]);
37
53
  const handlePasswordSubmit = useCallback(async (e)=>{
38
54
  e.preventDefault();
@@ -2,6 +2,7 @@
2
2
  import { useState, useCallback, useEffect } from 'react';
3
3
  import { useRouter } from 'next/navigation';
4
4
  import { verifyOtp, sendOtp } from '../services/authService.js';
5
+ import { pluginConfig } from '../../../config.js';
5
6
  /**
6
7
  * State machine for OTP verification: input → verify → redirect | resend.
7
8
  */ export function useVerifyOtpFlow({ email, purpose, redirectTo = '/' }) {
@@ -10,7 +11,8 @@ import { verifyOtp, sendOtp } from '../services/authService.js';
10
11
  const [isLoading, setIsLoading] = useState(false);
11
12
  const [error, setError] = useState(null);
12
13
  const [isResending, setIsResending] = useState(false);
13
- const [resendCooldown, setResendCooldown] = useState(0);
14
+ // Start with 30s cooldown since a code was just sent before arriving here
15
+ const [resendCooldown, setResendCooldown] = useState(30);
14
16
  useEffect(()=>{
15
17
  if (resendCooldown > 0) {
16
18
  const timer = setTimeout(()=>setResendCooldown((c)=>c - 1), 1000);
@@ -26,11 +28,15 @@ import { verifyOtp, sendOtp } from '../services/authService.js';
26
28
  try {
27
29
  const data = await verifyOtp(email, otp);
28
30
  if (data.success) {
31
+ const { passwordLogin: passwordLoginEnabled, otpLogin: otpLoginEnabled } = pluginConfig;
29
32
  if (purpose === 'password-reset') {
33
+ // Always allow setting password from explicit password-reset flow
30
34
  router.push(`/set-password?redirect=${encodeURIComponent(redirectTo)}`);
31
- } else if (data.isNewUser) {
35
+ } else if (!otpLoginEnabled && passwordLoginEnabled && data.isNewUser) {
36
+ // Only prompt for password if OTP login is disabled and password login is enabled
32
37
  router.push(`/set-password?redirect=${encodeURIComponent(redirectTo)}`);
33
38
  } else {
39
+ // OTP login is enabled — go straight to the app
34
40
  window.location.href = redirectTo;
35
41
  }
36
42
  } else {
@@ -22,5 +22,6 @@ export declare function setUserPassword(password: string, confirmPassword: strin
22
22
  export declare function signup(name: string, email: string): Promise<SignupResponse>;
23
23
  /**
24
24
  * Redirect the browser to the Google OAuth login endpoint.
25
+ * Uses payload-oauth2 plugin's route at /api/users/oauth/google.
25
26
  */
26
27
  export declare function initiateGoogleLogin(redirectTo?: string): void;
@@ -80,10 +80,11 @@ const API_PREFIX = '/api/auth';
80
80
  }
81
81
  /**
82
82
  * Redirect the browser to the Google OAuth login endpoint.
83
+ * Uses payload-oauth2 plugin's route at /api/users/oauth/google.
83
84
  */ export function initiateGoogleLogin(redirectTo = '/') {
84
85
  const params = new URLSearchParams();
85
86
  if (redirectTo !== '/') {
86
- params.set('redirect', redirectTo);
87
+ params.set('state', redirectTo);
87
88
  }
88
89
  const qs = params.toString();
89
90
  window.location.href = `/api/users/oauth/google${qs ? `?${qs}` : ''}`;
@@ -0,0 +1,27 @@
1
+ import { type AuthStyle } from '../config';
2
+ export interface AuthClientInitProps {
3
+ /** Override UI style. If omitted, reads from plugin config. */
4
+ style?: AuthStyle;
5
+ /** Override Google OAuth visibility. If omitted, reads from plugin config. */
6
+ googleOAuthEnabled?: boolean;
7
+ }
8
+ /**
9
+ * Drop this component into your root layout to sync the server-side
10
+ * plugin config to client components. No props needed — it reads
11
+ * everything from the plugin configuration automatically.
12
+ *
13
+ * ```tsx
14
+ * // app/(frontend)/layout.tsx
15
+ * import { AuthClientInit } from '@main12/auth-login/client'
16
+ *
17
+ * export default function Layout({ children }) {
18
+ * return (
19
+ * <html><body>
20
+ * <AuthClientInit />
21
+ * {children}
22
+ * </body></html>
23
+ * )
24
+ * }
25
+ * ```
26
+ */
27
+ export declare function AuthClientInit({ style, googleOAuthEnabled }?: AuthClientInitProps): null;
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+ import { pluginConfig, initClientConfig } from '../config.js';
3
+ /**
4
+ * Drop this component into your root layout to sync the server-side
5
+ * plugin config to client components. No props needed — it reads
6
+ * everything from the plugin configuration automatically.
7
+ *
8
+ * ```tsx
9
+ * // app/(frontend)/layout.tsx
10
+ * import { AuthClientInit } from '@main12/auth-login/client'
11
+ *
12
+ * export default function Layout({ children }) {
13
+ * return (
14
+ * <html><body>
15
+ * <AuthClientInit />
16
+ * {children}
17
+ * </body></html>
18
+ * )
19
+ * }
20
+ * ```
21
+ */ export function AuthClientInit({ style, googleOAuthEnabled } = {}) {
22
+ initClientConfig({
23
+ style: style ?? pluginConfig.style,
24
+ googleOAuthEnabled: googleOAuthEnabled ?? pluginConfig.googleOAuthEnabled,
25
+ passwordLogin: pluginConfig.passwordLogin,
26
+ otpLogin: pluginConfig.otpLogin
27
+ });
28
+ return null;
29
+ }
@@ -18,5 +18,13 @@ export interface AuthPagesProps {
18
18
  }) => Promise<void>;
19
19
  /** Base path prefix, defaults to '/auth'. Used to compute sibling URLs. */
20
20
  basePath?: string;
21
+ /** Show Google OAuth buttons. If omitted, reads from plugin config. */
22
+ showGoogleOAuth?: boolean;
23
+ /** Override the page background. Defaults to 'bg-white md:bg-[#191919]'. */
24
+ backgroundClass?: string;
25
+ /** UI style override. If omitted, reads from plugin config. */
26
+ style?: 'tailwind' | 'hero-ui';
27
+ /** Allow new user signups. When false, hides signup page and signup links. Defaults to true. */
28
+ allowSignup?: boolean;
21
29
  }
22
- export default function AuthPages({ slug, redirectTo, logo, onPasswordLogin, onSignup, basePath, }: AuthPagesProps): import("react/jsx-runtime").JSX.Element;
30
+ export default function AuthPages({ slug, redirectTo, logo, onPasswordLogin, onSignup, basePath, showGoogleOAuth, backgroundClass, style, allowSignup, }: AuthPagesProps): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { pluginConfig, initClientConfig } from '../config.js';
3
4
  import LoginPage from './pages/LoginPage.js';
4
5
  import SignupPage from './pages/SignupPage.js';
5
6
  import ForgotPasswordPage from './pages/ForgotPasswordPage.js';
@@ -37,21 +38,39 @@ const defaultSignup = async ({ name, email })=>{
37
38
  throw new Error(err.message || 'Signup failed');
38
39
  }
39
40
  };
40
- export default function AuthPages({ slug, redirectTo = '/admin', logo, onPasswordLogin = defaultPasswordLogin, onSignup = defaultSignup, basePath = '/auth' }) {
41
+ export default function AuthPages({ slug, redirectTo = '/admin', logo, onPasswordLogin = defaultPasswordLogin, onSignup = defaultSignup, basePath = '/auth', showGoogleOAuth, backgroundClass, style, allowSignup = true }) {
42
+ // Sync server plugin config to client using props (which come from the server via AuthPagesServer)
43
+ initClientConfig({
44
+ style: style ?? pluginConfig.style,
45
+ googleOAuthEnabled: showGoogleOAuth ?? pluginConfig.googleOAuthEnabled
46
+ });
41
47
  const page = slug?.[0] ?? 'login';
42
48
  const base = basePath.replace(/\/$/, '');
43
49
  const shared = {
44
- logo
50
+ logo,
51
+ ...showGoogleOAuth !== undefined ? {
52
+ showGoogleOAuth
53
+ } : {},
54
+ ...backgroundClass !== undefined ? {
55
+ backgroundClass
56
+ } : {}
45
57
  };
46
58
  switch(page){
47
59
  case 'login':
48
60
  return /*#__PURE__*/ _jsx(LoginPage, {
49
61
  onPasswordLogin: onPasswordLogin,
50
62
  redirectTo: redirectTo,
51
- signupUrl: `${base}/signup`,
63
+ signupUrl: allowSignup ? `${base}/signup` : undefined,
52
64
  ...shared
53
65
  });
54
66
  case 'signup':
67
+ if (!allowSignup) {
68
+ return /*#__PURE__*/ _jsx(LoginPage, {
69
+ onPasswordLogin: onPasswordLogin,
70
+ redirectTo: redirectTo,
71
+ ...shared
72
+ });
73
+ }
55
74
  return /*#__PURE__*/ _jsx(SignupPage, {
56
75
  onSignup: onSignup,
57
76
  loginUrl: `${base}/login`,
@@ -0,0 +1,17 @@
1
+ import type { AuthPagesProps } from './AuthPages';
2
+ export type { AuthPagesProps };
3
+ /**
4
+ * Server component wrapper for AuthPages.
5
+ * Reads plugin config via env vars (set by the plugin at init time)
6
+ * and passes it to the client component automatically.
7
+ *
8
+ * ```tsx
9
+ * // app/(auth)/auth/[...slug]/page.tsx (NO 'use client' needed!)
10
+ * import { AuthPages } from '@main12/auth-login/rsc'
11
+ * export default async function Page({ params }) {
12
+ * const { slug } = await params
13
+ * return <AuthPages slug={slug} />
14
+ * }
15
+ * ```
16
+ */
17
+ export default function AuthPages(props: AuthPagesProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import AuthPagesClient from './AuthPages.js';
3
+ /**
4
+ * Server component wrapper for AuthPages.
5
+ * Reads plugin config via env vars (set by the plugin at init time)
6
+ * and passes it to the client component automatically.
7
+ *
8
+ * ```tsx
9
+ * // app/(auth)/auth/[...slug]/page.tsx (NO 'use client' needed!)
10
+ * import { AuthPages } from '@main12/auth-login/rsc'
11
+ * export default async function Page({ params }) {
12
+ * const { slug } = await params
13
+ * return <AuthPages slug={slug} />
14
+ * }
15
+ * ```
16
+ */ export default function AuthPages(props) {
17
+ const googleOAuthEnabled = process.env.AUTH_PLUGIN_GOOGLE_OAUTH === 'true';
18
+ const style = process.env.AUTH_PLUGIN_STYLE || 'tailwind';
19
+ const allowSignup = process.env.AUTH_PLUGIN_ALLOW_SIGNUP !== 'false';
20
+ return /*#__PURE__*/ _jsx(AuthPagesClient, {
21
+ ...props,
22
+ showGoogleOAuth: props.showGoogleOAuth ?? googleOAuthEnabled,
23
+ style: props.style ?? style,
24
+ allowSignup: props.allowSignup ?? allowSignup
25
+ });
26
+ }
@@ -52,7 +52,7 @@ export default function ForgotPasswordPageHero({ loginUrl = '/login', logo, powe
52
52
  children: "Email"
53
53
  }),
54
54
  /*#__PURE__*/ _jsx(Input, {
55
- className: "bg-white"
55
+ variant: "secondary"
56
56
  })
57
57
  ]
58
58
  }),
@@ -23,7 +23,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
23
23
  poweredBy: poweredBy,
24
24
  cardClassName: cardClassName,
25
25
  backgroundClass: backgroundClass,
26
- footer: /*#__PURE__*/ _jsxs("p", {
26
+ footer: signupUrl ? /*#__PURE__*/ _jsxs("p", {
27
27
  className: "text-center text-gray-600 text-sm",
28
28
  children: [
29
29
  "Don't have an account?",
@@ -34,7 +34,7 @@ function LoginHeroContent({ onPasswordLogin, redirectTo = '/', showGoogleOAuth =
34
34
  children: "Sign up"
35
35
  })
36
36
  ]
37
- }),
37
+ }) : undefined,
38
38
  children: /*#__PURE__*/ _jsxs(AnimatePresence, {
39
39
  mode: "wait",
40
40
  children: [