@insforge/nextjs 0.7.5 → 0.7.8

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
@@ -1,39 +1,30 @@
1
1
  # @insforge/nextjs
2
2
 
3
- **Zero-configuration authentication for Next.js** using Insforge backend. Authentication pages are hosted on your backend by default—no UI code needed.
3
+ **Zero-configuration authentication for Next.js** using Insforge backend. Get production-ready auth in 5 minutes.
4
4
 
5
- ## Why Built-in Auth?
6
-
7
- ✅ **Zero UI Code** - No SignIn/SignUp pages to create
8
- ✅ **5-Minute Setup** - Provider + API route + callback page = done
9
- ✅ **Production Ready** - Battle-tested auth UI maintained by Insforge
10
- ✅ **Auto OAuth** - 11 providers configured automatically from backend
11
- ✅ **AI-Friendly** - Minimal code generation = fewer tokens
12
-
13
- **Use custom components only if you need highly customized branding or custom fields.**
5
+ ## Why @insforge/nextjs?
14
6
 
15
- ## Features
7
+ **Built-in Auth Pages** - Backend-hosted UI, no React code needed
8
+ ✅ **5-Minute Setup** - Provider + API route + callback + middleware = done
9
+ ✅ **Full SSR Support** - Works with Next.js App Router and Server Components
10
+ ✅ **Auto OAuth** - 11 providers configured from backend automatically
11
+ ✅ **TypeScript First** - Complete type safety out of the box
16
12
 
17
- - **Built-in Authentication**: Backend-hosted sign-in/sign-up pages (default)
18
- - **OAuth Support**: Google, GitHub, Discord, Facebook, LinkedIn, Microsoft, Apple, X, Instagram, TikTok, Spotify
19
- - **React Hooks**: `useAuth()`, `useUser()`, `useSession()`
20
- - **Control Components**: `<SignedIn>`, `<SignedOut>`, `<Protect>`
21
- - **Next.js Middleware**: Server-side route protection
22
- - **TypeScript**: Full type safety
13
+ **Need custom UI?** Scroll to [Advanced Usage](#advanced-usage) for custom components and styling.
23
14
 
24
15
  ## Installation
25
16
 
26
17
  ```bash
27
- npm install @insforge/nextjs @insforge/sdk
18
+ npm install @insforge/nextjs
28
19
  ```
29
20
 
30
- <Note>
31
- **SDK Integration**: `@insforge/nextjs` works seamlessly with `@insforge/sdk`. The SDK handles API calls, token management, and OAuth callback detection automatically. Always use SDK methods instead of raw `fetch` calls.
32
- </Note>
21
+ ---
33
22
 
34
23
  ## Quick Start
35
24
 
36
- ### 1. Add InsforgeProvider
25
+ ### 1. Setup Provider
26
+
27
+ Wrap your app with `InsforgeProvider` in the root layout:
37
28
 
38
29
  ```tsx
39
30
  // app/layout.tsx
@@ -52,9 +43,15 @@ export default function RootLayout({ children }: { children: React.ReactNode })
52
43
  }
53
44
  ```
54
45
 
55
- > **✨ Auto-styled**: Component styles are automatically loaded when you add `InsforgeProvider`. No CSS imports needed!
46
+ **Props:**
47
+ - `baseUrl` (required): Your Insforge backend URL
48
+ - `onAuthChange` (optional): Callback when auth state changes
49
+
50
+ > **Auto-styled**: Component styles are automatically injected. No CSS imports needed!
56
51
 
57
- ### 2. Create API route (enables SSR)
52
+ ### 2. Create API Route
53
+
54
+ Create an API route to sync tokens to HTTP-only cookies (enables SSR):
58
55
 
59
56
  ```tsx
60
57
  // app/api/auth/route.ts
@@ -70,98 +67,67 @@ export const GET = handlers.GET;
70
67
  export const DELETE = handlers.DELETE;
71
68
  ```
72
69
 
73
- > **Why?** Syncs auth tokens to HTTP-only cookies for server-side middleware.
70
+ **What it does:**
71
+ - `POST /api/auth` - Syncs localStorage token to HTTP-only cookie
72
+ - `GET /api/auth` - Retrieves user data server-side
73
+ - `DELETE /api/auth` - Clears auth cookie on sign out
74
+
75
+ ### 3. Create Callback Page
74
76
 
75
- ### 3. Create callback page
77
+ Create a callback page to complete the authentication flow. Use the `<InsforgeCallback>` component that handles everything automatically:
76
78
 
77
- <Note>
78
- **SDK Integration**: This callback page uses `@insforge/sdk` to automatically detect and handle URL parameters. The SDK handles token storage automatically, making the callback page simpler and more reliable.
79
- </Note>
79
+ - Detects authentication errors from backend
80
+ - Validates authentication tokens
81
+ - Syncs tokens to HTTP-only cookies for SSR
82
+ - Redirects to the destination page
80
83
 
81
84
  ```tsx
82
85
  // app/auth/callback/page.tsx
83
86
  'use client';
84
87
 
85
- import { useEffect, useRef, Suspense } from 'react';
86
- import { useRouter, useSearchParams } from 'next/navigation';
87
- import { createClient } from '@insforge/sdk';
88
-
89
- function CallbackContent() {
90
- const router = useRouter();
91
- const searchParams = useSearchParams();
92
- const isProcessingRef = useRef(false);
93
-
94
- useEffect(() => {
95
- const processCallback = async () => {
96
- if (isProcessingRef.current) return;
97
- isProcessingRef.current = true;
98
-
99
- const error = searchParams.get('error');
100
- if (error) {
101
- router.push('/?error=' + encodeURIComponent(error));
102
- return;
103
- }
104
-
105
- // Create SDK client - it automatically detects and stores URL parameters
106
- // SDK's detectOAuthCallback() handles: access_token, user_id, email, name
107
- // This automatically stores token in 'insforge-auth-token' and basic user info
108
- const insforge = createClient({
109
- baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,
110
- });
111
-
112
- // Fetch complete user data (including profile) using SDK method
113
- const { data: userData, error: userError } = await insforge.auth.getCurrentUser();
114
-
115
- if (userError || !userData) {
116
- router.push('/?error=authentication_failed');
117
- return;
118
- }
119
-
120
- // Store complete user profile for InsforgeProvider (enables instant UI updates)
121
- localStorage.setItem('insforge-user-profile', JSON.stringify(userData));
122
-
123
- // Sync token to HTTP-only cookie (for server-side middleware)
124
- const token = localStorage.getItem('insforge-auth-token');
125
- if (token) {
126
- await fetch('/api/auth', {
127
- method: 'POST',
128
- headers: { 'Content-Type': 'application/json' },
129
- body: JSON.stringify({ action: 'sync-token', token }),
130
- });
131
- }
88
+ import { InsforgeCallback } from '@insforge/nextjs';
132
89
 
133
- // Clean up URL and redirect
134
- window.history.replaceState({}, '', '/auth/callback');
135
- const destination = sessionStorage.getItem('auth_destination') || '/';
136
- sessionStorage.removeItem('auth_destination');
137
- setTimeout(() => router.push(destination), 100);
138
- };
90
+ export default function CallbackPage() {
91
+ return <InsforgeCallback />;
92
+ }
93
+ ```
139
94
 
140
- processCallback();
141
- }, [searchParams, router]);
95
+ **Optional: Custom loading UI**
142
96
 
97
+ ```tsx
98
+ export default function CallbackPage() {
143
99
  return (
144
- <div className="flex items-center justify-center min-h-screen">
145
- <div className="text-center">
146
- <h2 className="text-2xl font-semibold mb-4">Completing authentication...</h2>
147
- <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
148
- </div>
149
- </div>
100
+ <InsforgeCallback
101
+ loadingComponent={
102
+ <div className="flex items-center justify-center min-h-screen">
103
+ <div className="text-center">
104
+ <h2 className="text-2xl font-semibold mb-4">Signing you in...</h2>
105
+ <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
106
+ </div>
107
+ </div>
108
+ }
109
+ />
150
110
  );
151
111
  }
112
+ ```
113
+
114
+ **Optional: Custom redirect and callbacks**
152
115
 
116
+ ```tsx
153
117
  export default function CallbackPage() {
154
118
  return (
155
- <Suspense fallback={<div>Loading...</div>}>
156
- <CallbackContent />
157
- </Suspense>
119
+ <InsforgeCallback
120
+ redirectTo="/dashboard"
121
+ onSuccess={() => console.log('Authentication successful!')}
122
+ onError={(error) => console.error('Authentication failed:', error)}
123
+ />
158
124
  );
159
125
  }
160
126
  ```
161
127
 
162
- > **Why SDK?** The SDK automatically detects URL parameters (`access_token`, `user_id`, `email`, `name`) and stores them. Using SDK methods ensures consistency and reduces errors.
128
+ ### 4. Setup Middleware
163
129
 
164
- ### 4. Add middleware (protects routes)
130
+ Protect routes with middleware:
165
131
 
166
132
  ```ts
167
133
  // middleware.ts
@@ -178,7 +144,12 @@ export const config = {
178
144
  };
179
145
  ```
180
146
 
181
- ### 5. Use in components
147
+ **What it does:**
148
+ - Redirects unauthenticated users to backend auth pages
149
+ - Verifies tokens server-side
150
+ - Allows public routes without auth
151
+
152
+ ### 5. Use Hooks & Components
182
153
 
183
154
  ```tsx
184
155
  // app/page.tsx
@@ -188,6 +159,7 @@ export default function Home() {
188
159
  return (
189
160
  <div>
190
161
  <SignedOut>
162
+ {/* Clicking will redirect to backend auth page */}
191
163
  <a href="/sign-in">Sign In</a>
192
164
  </SignedOut>
193
165
 
@@ -200,152 +172,256 @@ export default function Home() {
200
172
  }
201
173
  ```
202
174
 
203
- **That's it!** When users click "Sign In", they'll be redirected to your backend's auth page automatically.
175
+ **Available Components:**
176
+ - `<SignedIn>` - Shows children only when authenticated
177
+ - `<SignedOut>` - Shows children only when not authenticated
178
+ - `<UserButton>` - User profile button with dropdown
179
+ - `<Protect>` - Conditional rendering with custom logic
180
+
181
+ **Available Hooks:**
182
+
183
+ ```tsx
184
+ import { useAuth, useUser } from '@insforge/nextjs';
185
+
186
+ function Component() {
187
+ const { signIn, signUp, signOut, isSignedIn, isLoaded } = useAuth();
188
+ const { user, updateUser } = useUser();
189
+
190
+ return <div>Email: {user?.email}</div>;
191
+ }
192
+ ```
193
+
194
+ **That's it!** 🎉 Your app now has production-ready authentication.
204
195
 
205
196
  ---
206
197
 
207
198
  ## How It Works
208
199
 
209
200
  ```
210
- 1. User clicks "Sign In" → Middleware detects no auth
201
+ 1. User clicks "Sign In" → Middleware redirects to backend
211
202
 
212
- 2. Redirects to: https://backend.insforge.app/auth/signin?redirect=yourapp.com/auth/callback
203
+ 2. User signs in on backend-hosted page (https://backend.insforge.app/auth/signin)
213
204
 
214
- 3. User signs in on backend's hosted page
205
+ 3. Backend redirects: yourapp.com/auth/callback?access_token=xxx&user_id=xxx...
215
206
 
216
- 4. Backend redirects: yourapp.com/auth/callback?access_token=xxx
207
+ 4. <InsforgeCallback> component:
208
+ - SDK auto-detects and stores token
209
+ - Reloads auth state in provider
210
+ - Syncs token to HTTP-only cookie
211
+ - Redirects to destination
217
212
 
218
- 5. Callback stores token (localStorage + cookie) → User sees /dashboard
213
+ 5. User sees dashboard with authenticated state
219
214
  ```
220
215
 
221
- **Why API route + callback?**
222
- - **API route**: Syncs tokens to HTTP-only cookies (enables server-side middleware)
223
- - **Callback page**: Receives tokens from backend auth pages (OAuth + email/password) and uses SDK to handle them automatically
216
+ **Two-Storage Architecture:**
217
+ - **localStorage**: Client-side token access (hooks, components, SDK)
218
+ - **HTTP-only cookie**: Server-side token access (middleware, SSR)
224
219
 
225
220
  ---
226
221
 
227
222
  ## Local Development
228
223
 
229
- Backend typically runs on different port during local dev:
224
+ During local development, backend typically runs on a different port:
230
225
 
231
226
  ```bash
232
227
  # .env.local
233
- NEXT_PUBLIC_INSFORGE_BASE_URL=http://localhost:7130 # Backend API
234
- NEXT_PUBLIC_INSFORGE_FRONTEND_URL=http://localhost:7131 # Backend Frontend (auth pages)
235
- INSFORGE_BASE_URL=http://localhost:7130 # For middleware
228
+ NEXT_PUBLIC_INSFORGE_BASE_URL=http://localhost:7130 # Backend API URL
229
+ INSFORGE_BASE_URL=http://localhost:7130 # Backend API URL (for server-side)
236
230
  ```
237
231
 
238
- Provider automatically uses `NEXT_PUBLIC_INSFORGE_FRONTEND_URL` for auth redirects if set.
232
+ Both variables should point to your Insforge backend URL.
239
233
 
240
234
  ---
241
235
 
242
- ---
236
+ ## Advanced Usage
243
237
 
244
- ## API Reference
238
+ ### Custom Auth Components
245
239
 
246
- ### Hooks
240
+ Want custom branding or additional fields? Create custom auth pages:
247
241
 
248
- #### `useAuth()`
242
+ ```tsx
243
+ // app/sign-in/page.tsx
244
+ 'use client';
249
245
 
250
- Access authentication methods (uses SDK internally):
246
+ import { SignIn } from '@insforge/nextjs';
247
+ import { useRouter } from 'next/navigation';
251
248
 
252
- ```tsx
253
- import { useAuth } from '@insforge/nextjs';
249
+ export default function SignInPage() {
250
+ const router = useRouter();
254
251
 
255
- function Component() {
256
- const { signIn, signUp, signOut, isSignedIn, isLoaded } = useAuth();
257
-
258
- async function handleSignIn(email: string, password: string) {
259
- try {
260
- await signIn(email, password); // Uses SDK internally
261
- } catch (error) {
262
- console.error('Sign in failed:', error);
263
- }
264
- }
265
-
266
252
  return (
267
- <div>
268
- {isSignedIn && <button onClick={() => signOut()}>Sign Out</button>}
253
+ <div className="min-h-screen flex items-center justify-center bg-gray-50">
254
+ <SignIn
255
+ afterSignInUrl="/dashboard"
256
+ onSuccess={(user) => {
257
+ console.log('Signed in:', user);
258
+ router.push('/dashboard');
259
+ }}
260
+ onError={(error) => {
261
+ console.error('Sign in error:', error);
262
+ }}
263
+ />
269
264
  </div>
270
265
  );
271
266
  }
272
267
  ```
273
268
 
274
- **Returns**: `signIn()`, `signUp()`, `signOut()`, `isLoaded`, `isSignedIn`
275
-
276
- #### `useUser()`
269
+ ```tsx
270
+ // app/sign-up/page.tsx
271
+ 'use client';
277
272
 
278
- Access current user data (from SDK-managed storage):
273
+ import { SignUp } from '@insforge/nextjs';
279
274
 
280
- ```tsx
281
- import { useUser } from '@insforge/nextjs';
282
-
283
- function UserProfile() {
284
- const { user, isLoaded, updateUser } = useUser();
285
-
286
- if (!isLoaded) return <div>Loading...</div>;
287
- if (!user) return <div>Not signed in</div>;
288
-
275
+ export default function SignUpPage() {
289
276
  return (
290
- <div>
291
- <p>Email: {user.email}</p>
292
- {user.nickname && <p>Nickname: {user.nickname}</p>}
277
+ <div className="min-h-screen flex items-center justify-center bg-gray-50">
278
+ <SignUp afterSignUpUrl="/onboarding" />
293
279
  </div>
294
280
  );
295
281
  }
296
282
  ```
297
283
 
298
- **Returns**: `user`, `isLoaded`, `updateUser()`
299
-
300
- #### `useSession()`
301
-
302
- Access session data (from SDK-managed storage):
303
-
304
- ```tsx
305
- import { useSession } from '@insforge/nextjs';
306
-
307
- function SessionInfo() {
308
- const { session, isLoaded } = useSession();
309
-
310
- if (!isLoaded) return <div>Loading...</div>;
311
- if (!session) return <div>No active session</div>;
312
-
313
- return <div>User ID: {session.userId}</div>;
314
- }
315
- ```
316
-
317
- **Returns**: `session`, `isLoaded`
284
+ **SignIn Props:**
285
+ - `afterSignInUrl` - Redirect URL after successful sign in
286
+ - `title` / `subtitle` - Custom heading text
287
+ - `emailLabel` / `passwordLabel` - Custom field labels
288
+ - `submitButtonText` / `loadingButtonText` - Custom button text
289
+ - `appearance` - Tailwind CSS classes for styling
290
+ - `onSuccess` / `onError` - Callback functions
318
291
 
319
- ### Components
292
+ **SignUp Props:** Same as SignIn, plus:
293
+ - `afterSignUpUrl` - Redirect URL after successful sign up
294
+ - Additional text customization options
320
295
 
321
- #### `<SignIn>` / `<SignUp>`
296
+ ### Styling Components
322
297
 
323
- Pre-built auth forms (only with `useBuiltInAuth={false}`):
298
+ All components support an `appearance` prop for Tailwind CSS customization:
324
299
 
325
300
  ```tsx
326
- <SignIn afterSignInUrl="/dashboard" />
327
- <SignUp afterSignUpUrl="/onboarding" />
301
+ <SignIn
302
+ appearance={{
303
+ containerClassName: "shadow-2xl",
304
+ buttonClassName: "bg-blue-600 hover:bg-blue-700"
305
+ }}
306
+ />
307
+
308
+ <UserButton
309
+ mode="detailed"
310
+ appearance={{
311
+ containerClassName: "ml-auto",
312
+ buttonClassName: "hover:bg-gray-100",
313
+ nameClassName: "text-white",
314
+ emailClassName: "text-gray-300"
315
+ }}
316
+ />
328
317
  ```
329
318
 
330
- **Props**: `afterSignInUrl`/`afterSignUpUrl`, `appearance`, `onSuccess`, `onError`
319
+ **UserButton Modes:**
320
+ - `detailed` (default): Shows avatar + name + email
321
+ - `simple`: Shows avatar only
322
+
323
+ ### Building Custom Auth Forms
331
324
 
332
- #### `<UserButton>`
325
+ Use primitive components for complete customization:
333
326
 
334
327
  ```tsx
335
- <UserButton afterSignOutUrl="/" mode="detailed" />
328
+ import {
329
+ AuthContainer,
330
+ AuthHeader,
331
+ AuthFormField,
332
+ AuthPasswordField,
333
+ AuthSubmitButton,
334
+ AuthDivider,
335
+ AuthOAuthProviders,
336
+ AuthLink,
337
+ cn,
338
+ } from '@insforge/nextjs';
339
+
340
+ function CustomSignIn() {
341
+ return (
342
+ <AuthContainer
343
+ appearance={{
344
+ containerClassName: "max-w-md",
345
+ cardClassName: "bg-white"
346
+ }}
347
+ >
348
+ <AuthHeader
349
+ title="Welcome Back"
350
+ subtitle="Sign in to continue"
351
+ appearance={{
352
+ titleClassName: "text-3xl text-blue-900"
353
+ }}
354
+ />
355
+
356
+ <form onSubmit={handleSubmit}>
357
+ <AuthFormField
358
+ id="email"
359
+ type="email"
360
+ label="Email Address"
361
+ placeholder="you@example.com"
362
+ appearance={{
363
+ inputClassName: "border-blue-500 focus:ring-blue-500"
364
+ }}
365
+ />
366
+
367
+ <AuthPasswordField
368
+ id="password"
369
+ label="Password"
370
+ emailAuthConfig={config}
371
+ appearance={{
372
+ inputClassName: "border-blue-500"
373
+ }}
374
+ />
375
+
376
+ <AuthSubmitButton
377
+ isLoading={loading}
378
+ className="bg-blue-600 hover:bg-blue-700"
379
+ >
380
+ Sign In
381
+ </AuthSubmitButton>
382
+ </form>
383
+
384
+ <AuthDivider text="or" />
385
+
386
+ <AuthOAuthProviders
387
+ providers={['google', 'github']}
388
+ onClick={handleOAuth}
389
+ loading={oauthLoading}
390
+ appearance={{
391
+ buttonClassName: "hover:bg-gray-50"
392
+ }}
393
+ />
394
+
395
+ <AuthLink
396
+ text="Don't have an account?"
397
+ linkText="Sign up"
398
+ href="/sign-up"
399
+ />
400
+ </AuthContainer>
401
+ );
402
+ }
336
403
  ```
337
404
 
338
- **Props**: `afterSignOutUrl`, `mode` ('detailed' | 'simple'), `appearance`
405
+ **Available Primitive Components:**
406
+ - `AuthContainer` - Main form container
407
+ - `AuthHeader` - Title and subtitle
408
+ - `AuthFormField` - Standard input field
409
+ - `AuthPasswordField` - Password field with visibility toggle
410
+ - `AuthPasswordStrengthIndicator` - Password requirement checklist
411
+ - `AuthSubmitButton` - Submit button with loading states
412
+ - `AuthErrorBanner` - Error message display
413
+ - `AuthDivider` - Visual separator
414
+ - `AuthOAuthProviders` - OAuth provider buttons grid
415
+ - `AuthOAuthButton` - Individual OAuth button
416
+ - `AuthVerificationCodeInput` - OTP/2FA code input
417
+ - `AuthLink` - Navigation link
418
+ - `AuthBranding` - Insforge branding footer
339
419
 
340
- #### `<SignedIn>` / `<SignedOut>` / `<Protect>`
420
+ All components support `appearance` prop with specific `className` options for each element.
341
421
 
342
- ```tsx
343
- <SignedIn><Dashboard /></SignedIn>
344
- <SignedOut><LandingPage /></SignedOut>
345
- <Protect condition={(user) => user.role === 'admin'}><AdminPanel /></Protect>
346
- ```
422
+ ### Server-Side Usage
347
423
 
348
- ### Server-Side Helpers
424
+ Access auth data in Server Components:
349
425
 
350
426
  ```tsx
351
427
  // app/dashboard/page.tsx (Server Component)
@@ -356,66 +432,180 @@ import { createClient } from '@insforge/sdk';
356
432
  export default async function Dashboard() {
357
433
  const userId = getAuthUserId(headers());
358
434
  const token = getAuthToken(headers());
359
-
435
+
360
436
  if (!userId) {
361
437
  return <div>Not authenticated</div>;
362
438
  }
363
-
364
- // Use SDK to fetch user data server-side
439
+
440
+ // Use SDK for server-side data fetching
365
441
  const insforge = createClient({
366
442
  baseUrl: process.env.INSFORGE_BASE_URL!,
367
443
  edgeFunctionToken: token || undefined,
368
444
  });
369
-
445
+
370
446
  const { data: userData } = await insforge.auth.getCurrentUser();
371
-
447
+
372
448
  return <div>Welcome, {userData?.user.email}</div>;
373
449
  }
374
450
  ```
375
451
 
376
- ---
452
+ ### Conditional Rendering
453
+
454
+ ```tsx
455
+ import { Protect } from '@insforge/nextjs';
456
+
457
+ // Role-based access
458
+ <Protect condition={(user) => user.role === 'admin'}>
459
+ <AdminPanel />
460
+ </Protect>
377
461
 
378
- ### Auth Callbacks
462
+ // Custom logic
463
+ <Protect condition={(user) => user.emailVerified}>
464
+ <VerifiedUserFeature />
465
+ </Protect>
466
+ ```
467
+
468
+ ### Auth Change Callback
469
+
470
+ Track authentication events:
379
471
 
380
472
  ```tsx
381
- <InsforgeProvider
473
+ <InsforgeProvider
382
474
  baseUrl={baseUrl}
383
- onAuthChange={(user) => user && analytics.identify(user.id)}
475
+ onAuthChange={(user) => {
476
+ if (user) {
477
+ // User signed in
478
+ analytics.identify(user.id);
479
+ } else {
480
+ // User signed out
481
+ analytics.reset();
482
+ }
483
+ }}
384
484
  />
385
485
  ```
386
486
 
387
487
  ---
388
488
 
389
- ## SDK + Next.js Package = Complete Solution
489
+ ## API Reference
390
490
 
391
- The `@insforge/nextjs` package works seamlessly with `@insforge/sdk`:
491
+ ### InsforgeProvider Props
392
492
 
393
- - **SDK handles**: API calls, token management, OAuth callback detection, user data fetching
394
- - **Next.js package handles**: React components, hooks, middleware, SSR support
493
+ ```tsx
494
+ interface InsforgeProviderProps {
495
+ baseUrl: string; // Insforge backend URL
496
+ onAuthChange?: (user: InsforgeUser | null) => void; // Auth state change callback
497
+ }
498
+ ```
395
499
 
396
- Always use SDK methods (`insforge.auth.getCurrentUser()`, `insforge.auth.signIn()`, etc.) instead of raw `fetch` calls. This ensures consistency, type safety, and automatic error handling.
500
+ ### InsforgeCallback Props
397
501
 
398
- ## Why @insforge/nextjs?
502
+ ```tsx
503
+ interface InsforgeCallbackProps {
504
+ redirectTo?: string; // Custom redirect destination after auth
505
+ onSuccess?: () => void; // Callback fired on successful authentication
506
+ onError?: (error: string) => void; // Callback fired on authentication error
507
+ loadingComponent?: ReactNode; // Custom loading UI during authentication
508
+ }
509
+ ```
510
+
511
+ **Default behavior:**
512
+ - Redirects to `sessionStorage['auth_destination']` or `sessionStorage['oauth_final_destination']` or `'/'`
513
+ - Displays a built-in loading spinner during authentication
514
+ - Handles errors by redirecting to `/?error=<error_message>`
515
+
516
+ ### useAuth()
517
+
518
+ ```tsx
519
+ const {
520
+ signIn, // (email: string, password: string) => Promise<void>
521
+ signUp, // (email: string, password: string) => Promise<void>
522
+ signOut, // () => Promise<void>
523
+ isSignedIn, // boolean
524
+ isLoaded, // boolean
525
+ } = useAuth();
526
+ ```
527
+
528
+ ### useUser()
529
+
530
+ ```tsx
531
+ const {
532
+ user, // InsforgeUser | null
533
+ isLoaded, // boolean
534
+ updateUser, // (data: Partial<InsforgeUser>) => Promise<void>
535
+ } = useUser();
536
+ ```
537
+
538
+ **InsforgeUser Type:**
539
+ ```tsx
540
+ interface InsforgeUser {
541
+ id: string;
542
+ email: string;
543
+ nickname?: string;
544
+ avatarUrl?: string;
545
+ role?: string;
546
+ emailVerified?: boolean;
547
+ }
548
+ ```
549
+
550
+ ### Middleware Helpers
399
551
 
400
- **For Developers**: 5-minute auth setup instead of hours. Production-ready security and session management included. SDK integration means less code to write and maintain.
552
+ ```tsx
553
+ import { getAuthUserId, getAuthToken } from '@insforge/nextjs/middleware';
554
+
555
+ const userId = getAuthUserId(headers()); // string | null
556
+ const token = getAuthToken(headers()); // string | null
557
+ ```
401
558
 
402
- **For AI Agents**: Minimal code generation (5 files vs 20+ for custom auth). SDK-first approach reduces errors. Consistent patterns across projects.
559
+ ### Utility Function
560
+
561
+ ```tsx
562
+ import { cn } from '@insforge/nextjs';
563
+
564
+ // Merge Tailwind classes (uses clsx + tailwind-merge)
565
+ const className = cn("px-4 py-2", "bg-blue-500", conditionalClass);
566
+ ```
403
567
 
404
568
  ---
405
569
 
406
570
  ## TypeScript
407
571
 
572
+ Full TypeScript support with exported types:
573
+
408
574
  ```tsx
409
- import type { InsforgeUser, InsforgeSession, AuthContextValue } from '@insforge/nextjs';
575
+ import type {
576
+ InsforgeUser,
577
+ InsforgeCallbackProps,
578
+ SignInProps,
579
+ SignUpProps,
580
+ UserButtonProps,
581
+ ProtectProps,
582
+ OAuthProviderConfig,
583
+ } from '@insforge/nextjs';
410
584
  ```
411
585
 
412
586
  ---
413
587
 
588
+ ## Why @insforge/nextjs?
589
+
590
+ **For Developers:**
591
+ - ⚡️ 5-minute setup vs hours of custom auth code
592
+ - 🔒 Production-ready security and session management
593
+ - 🎨 Customizable components when needed
594
+ - 🚀 Built-in SSR support for Next.js App Router
595
+
596
+ **For AI Agents:**
597
+ - 📝 Minimal code generation (5 files vs 20+ for custom auth)
598
+ - 🎯 Consistent patterns across projects
599
+ - 🤖 SDK-first approach reduces errors
600
+ - 💰 Less tokens used per setup
601
+
602
+ ---
603
+
414
604
  ## Support
415
605
 
416
- - **Docs**: https://docs.insforge.dev/introduction
417
- - **Issues**: https://github.com/InsForge/InsForge/issues
418
- - **Discord**: https://discord.com/invite/DvBtaEc9Jz
606
+ - **Documentation**: https://docs.insforge.dev
607
+ - **GitHub Issues**: https://github.com/InsForge/InsForge/issues
608
+ - **Discord Community**: https://discord.com/invite/DvBtaEc9Jz
419
609
 
420
610
  ## License
421
611