The @insforge/nextjs package provides zero-configuration authentication for Next.js applications. Authentication pages are hosted on your backend by default—no UI code needed.
Quick Start
Step 1: Install Package and Set Environment Variables
npm install @insforge/nextjs@latest
NEXT_PUBLIC_INSFORGE_BASE_URL=https://your-app.region.insforge.app
Step 2: Add Middleware
Create middleware to protect routes:
import { InsforgeMiddleware } from '@insforge/nextjs/middleware';
export default InsforgeMiddleware({
baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL || 'https://your-app.region.insforge.app', // Replace with your InsForge backend URL
publicRoutes: ['/'],
});
export const config = {
matcher: [
'/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
],
};
Step 3: Create API Route
Create an API route to enable server-side rendering (SSR) and cookie-based authentication:
import { createAuthRouteHandlers } from '@insforge/nextjs/api';
const handlers = createAuthRouteHandlers({
baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL || 'https://your-app.region.insforge.app', // Replace with your InsForge backend URL
});
export const POST = handlers.POST;
export const GET = handlers.GET;
export const DELETE = handlers.DELETE;
Why? This route syncs auth tokens to HTTP-only cookies for server-side middleware.
Step 4: Add InsforgeProvider
Wrap your application with the InsforgeProvider in your root layout:
import {
InsforgeProvider,
SignedIn,
SignedOut,
SignInButton,
SignUpButton,
UserButton,
} from '@insforge/nextjs';
export const metadata: Metadata = {
title: 'InsForge Next.js Quickstart',
description: 'Generated by create next app',
};
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<InsforgeProvider
baseUrl={
process.env.NEXT_PUBLIC_INSFORGE_BASE_URL || 'https://your-app.region.insforge.app' // Replace with your InsForge backend URL
}
>
<nav>
<SignedOut>
<SignInButton />
<SignUpButton />
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</nav>
{children}
</InsforgeProvider>
</body>
</html>
);
}
Preventing FOUC: The CSS import in your root layout ensures styles are loaded during
server-side rendering, preventing flash of unstyled content (FOUC). Without this import,
components may briefly appear unstyled when the page first loads.
That’s it! When users click “Sign In”, they’ll be redirected to your backend’s auth page automatically.
Next Steps
Client-side Hooks
useAuth()
Access authentication state in client side:
'use client';
import { useAuth } from '@insforge/nextjs';
function LoginButton() {
const { isSignedIn, isLoaded } = useAuth();
if (!isLoaded) return <div>Loading...</div>;
return <div>{isSignedIn ? 'Welcome!' : 'Sign In'}</div>;
}
Returns:
isSignedIn - Boolean auth state
isLoaded - Boolean loading state
useUser()
Access current user data in client side:
'use client';
import { useUser } from '@insforge/nextjs';
function UserProfile() {
const { user, isLoaded } = useUser();
if (!isLoaded) return <div>Loading...</div>;
if (!user) return <div>Not signed in</div>;
return (
<div>
<p>Id: {user.id}</p>
<p>Email: {user.email}</p>
<p>Name: {user.name}</p>
<img src={user.avatarUrl} alt="Avatar" />
</div>
);
}
Returns:
user - User object with id, email, name, avatarUrl
isLoaded - Boolean loading state
Server side functions
auth
Access current user data and access token in server side:
import { auth } from '@insforge/nextjs/server';
import { createClient } from '@insforge/sdk';
export async function POST(request: NextRequest) {
try {
// Authenticate the request and get user info
const { user, userId, token } = await auth();
// Parse request body to get the prompt
const { prompt } = await request.json();
// Create InsForge SDK
const insforge = createClient({
baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL || "https://your-app.region.insforge.app",
anonKey: token
});
// Request for AI response
const completion = await insforge.ai.chat.completions.create({
model: 'anthropic/claude-3.5-haiku',
messages: [
{
role: 'user',
content: prompt,
},
],
});
const generatedResponse = completion.choices[0].message.content.trim();
// Return success response
return NextResponse.json(
{
success: true,
data: generatedResponse,
},
{ status: 201 }
);
} catch (error) {
console.error(error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}