@insforge/nextjs 0.7.5 → 0.7.7

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