Skip to main content

Next.js SDK

Server and client utilities for Next.js. Supports App Router and Pages Router.

npm install @ainative/next-sdk

The Next.js SDK re-exports all React SDK hooks (useChat, useCredits, useMemory, etc.) from @ainative/next-sdk/client and adds server-side utilities via @ainative/next-sdk/server.


Server Client

Use createServerClient in API routes and Server Components to call the AINative API from the server. The client exposes chat.completions.create(), credits.balance(), deployments.*, and rerank().

// app/api/chat/route.ts
import { createServerClient } from '@ainative/next-sdk/server';

export async function POST(req: Request) {
const { messages } = await req.json();

const client = createServerClient({
apiKey: process.env.AINATIVE_API_KEY!,
});

const response = await client.chat.completions.create({
messages,
preferred_model: 'meta-llama/llama-3.3-70b-instruct',
temperature: 0.7,
});

return Response.json(response);
}

ServerClientConfig

OptionTypeDefaultDescription
apiKeystringrequiredJWT token or API key
baseUrlstringhttps://api.ainative.studio/api/v1API base URL

ServerClient Methods

MethodDescription
chat.completions.create(request)Create a chat completion
credits.balance()Get credit balance
deployments.list()List deployments
deployments.get(id)Get a deployment
deployments.create(options)Create a deployment
deployments.teardown(id)Delete a deployment
deployments.chatCompletions(id, messages, options?)Run inference on a deployment
rerank(query, documents, options?)Rerank documents

Auth Middleware (App Router)

Protect API routes with withAuth. It reads the JWT from the ainative_token cookie, validates it, and passes the session and apiKey to your handler.

// app/api/chat/route.ts
import { withAuth, createServerClient } from '@ainative/next-sdk/server';

export const POST = withAuth(async (req, { session, apiKey }) => {
const client = createServerClient({ apiKey });
const { messages } = await req.json();

const response = await client.chat.completions.create({
messages,
preferred_model: 'meta-llama/llama-3.3-70b-instruct',
});

return Response.json(response);
});

If the cookie is missing or the JWT is expired, withAuth returns a 401 response automatically.

Auth Middleware (Pages Router)

// pages/api/chat.ts
import { withAuthPages, createServerClient } from '@ainative/next-sdk/server';

export default withAuthPages(async (req, res, { session, apiKey }) => {
const client = createServerClient({ apiKey });

const response = await client.chat.completions.create({
messages: req.body.messages,
});

res.status(200).json(response);
});

Session Helpers

Read the current user session in Server Components:

// app/dashboard/page.tsx
import { getSession, getApiKey, createServerClient } from '@ainative/next-sdk/server';
import { redirect } from 'next/navigation';

export default async function DashboardPage() {
const session = await getSession();
if (!session) redirect('/login');

const apiKey = await getApiKey();
const client = createServerClient({ apiKey: apiKey! });
const balance = await client.credits.balance();

return (
<div>
<h1>Welcome, {session.email}</h1>
<p>Credits remaining: {balance.remaining_credits.toLocaleString()}</p>
</div>
);
}
FunctionRouterDescription
getSession(cookieName?)App RouterAsync -- reads from cookies()
getApiKey(cookieName?)App RouterAsync -- returns raw JWT string
getSessionFromCookie(cookieHeader, cookieName?)Pages RouterSync -- parses cookie header
getApiKeyFromCookie(cookieHeader, cookieName?)Pages RouterSync -- extracts token string

Client Components

For client-side interactivity, use the hooks re-exported from the React SDK. Import from @ainative/next-sdk/client (or @ainative/next-sdk directly).

'use client';

import { AINativeProvider, useChat, useCredits } from '@ainative/next-sdk/client';

function ChatUI() {
const { messages, sendMessage, isLoading, reset } = useChat({
model: 'meta-llama/llama-3.3-70b-instruct',
});
const { balance } = useCredits();
const [input, setInput] = React.useState('');

const handleSend = async () => {
if (!input.trim()) return;
setInput('');
await sendMessage([...messages, { role: 'user', content: input }]);
};

return (
<div>
<p>{balance?.remaining_credits} credits remaining</p>

{messages.map((msg, i) => (
<div key={i}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
{isLoading && <p>Thinking...</p>}

<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleSend()}
/>
<button onClick={handleSend} disabled={isLoading}>Send</button>
<button onClick={reset}>Clear</button>
</div>
);
}

// Wrap with provider (pass API key from server via props or env)
export default function ChatPage({ apiKey }: { apiKey: string }) {
return (
<AINativeProvider config={{ apiKey }}>
<ChatUI />
</AINativeProvider>
);
}

All hooks from the React SDK are available: useChat, useCredits, useMemory, useAgent, useTask, useThread, and the deployment hooks.


Full Example: Chat Page with Server + Client

A complete Next.js page that combines server-side auth with client-side chat.

API Route

// app/api/chat/route.ts
import { withAuth, createServerClient } from '@ainative/next-sdk/server';

export const POST = withAuth(async (req, { apiKey }) => {
const client = createServerClient({ apiKey });
const { messages } = await req.json();

const response = await client.chat.completions.create({
messages,
preferred_model: 'meta-llama/llama-3.3-70b-instruct',
});

return Response.json(response);
});

Server Component (layout)

// app/chat/page.tsx
import { getSession, getApiKey } from '@ainative/next-sdk/server';
import { redirect } from 'next/navigation';
import ChatClient from './chat-client';

export default async function ChatPage() {
const session = await getSession();
if (!session) redirect('/login');

const apiKey = await getApiKey();

return (
<main>
<h1>Chat</h1>
<p>Logged in as {session.email}</p>
<ChatClient apiKey={apiKey!} />
</main>
);
}

Client Component

// app/chat/chat-client.tsx
'use client';

import React, { useState } from 'react';
import { AINativeProvider, useChat, useCredits, useMemory } from '@ainative/next-sdk/client';

function ChatInterface() {
const { messages, sendMessage, isLoading, error, reset } = useChat({
model: 'meta-llama/llama-3.3-70b-instruct',
});
const { balance } = useCredits();
const { remember } = useMemory();
const [input, setInput] = useState('');

const handleSend = async () => {
if (!input.trim() || isLoading) return;
const text = input;
setInput('');

const response = await sendMessage([
...messages,
{ role: 'user', content: text },
]);

// Optionally store the exchange in memory
if (response) {
await remember(`User asked: ${text}`, { tags: ['chat'] });
}
};

return (
<div style={{ maxWidth: 640, margin: '0 auto' }}>
{balance && (
<div style={{ textAlign: 'right', fontSize: 14, color: '#666' }}>
{balance.remaining_credits.toLocaleString()} credits | {balance.plan}
</div>
)}

<div style={{ minHeight: 400, padding: 16 }}>
{messages.map((msg, i) => (
<div key={i} style={{
textAlign: msg.role === 'user' ? 'right' : 'left',
margin: '8px 0',
}}>
<span style={{
display: 'inline-block',
padding: '8px 12px',
borderRadius: 12,
background: msg.role === 'user' ? '#0066ff' : '#f0f0f0',
color: msg.role === 'user' ? '#fff' : '#000',
maxWidth: '80%',
}}>
{msg.content}
</span>
</div>
))}
{isLoading && <div style={{ color: '#999' }}>Thinking...</div>}
{error && <div style={{ color: 'red' }}>Error: {error.message}</div>}
</div>

<div style={{ display: 'flex', gap: 8 }}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleSend()}
placeholder="Type a message..."
style={{ flex: 1, padding: '8px 12px' }}
/>
<button onClick={handleSend} disabled={isLoading}>Send</button>
<button onClick={reset}>Clear</button>
</div>
</div>
);
}

export default function ChatClient({ apiKey }: { apiKey: string }) {
return (
<AINativeProvider config={{ apiKey }}>
<ChatInterface />
</AINativeProvider>
);
}

Environment Variables

VariableDescription
AINATIVE_API_KEYServer-side API key (used in createServerClient)

The server client does not auto-read environment variables -- you must pass the API key explicitly via createServerClient({ apiKey }).


TypeScript Types

import type {
Session,
ServerClient,
ServerClientConfig,
WithAuthOptions,
} from '@ainative/next-sdk/server';

import type {
AINativeConfig,
Message,
ChatCompletionResponse,
CreditBalance,
AINativeError,
} from '@ainative/next-sdk/client';

Next Steps