---
title: "Next.js SDK"
description: "@ainative/next-sdk — server client, auth middleware, streaming for Next.js"
canonical: "https://docs.ainative.studio/docs/sdks/nextjs"
last-updated: "2026-10-03T21:47:10.764Z"
---

# Next.js SDK

Source: https://docs.ainative.studio/docs/sdks/nextjs

> @ainative/next-sdk — server client, auth middleware, streaming for Next.js

# Next.js SDK

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

```bash
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()`.

```tsx
// 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

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `apiKey` | `string` | *required* | JWT token or API key |
| `baseUrl` | `string` | `https://api.ainative.studio/api/v1` | API base URL |

### ServerClient Methods

| Method | Description |
|--------|-------------|
| `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.

```tsx
// 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)

```tsx
// 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:

```tsx
// 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>
  );
}
```

| Function | Router | Description |
|----------|--------|-------------|
| `getSession(cookieName?)` | App Router | Async -- reads from `cookies()` |
| `getApiKey(cookieName?)` | App Router | Async -- returns raw JWT string |
| `getSessionFromCookie(cookieHeader, cookieName?)` | Pages Router | Sync -- parses cookie header |
| `getApiKeyFromCookie(cookieHeader, cookieName?)` | Pages Router | Sync -- 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).

```tsx
'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](/docs/sdks/react) 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

```tsx
// 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)

```tsx
// 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

```tsx
// 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

| Variable | Description |
|----------|-------------|
| `AINATIVE_API_KEY` | Server-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

```tsx
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

- [React SDK](/docs/sdks/react) -- Hook API reference and standalone examples
- [Build a Chatbot](/docs/examples/chatbot) -- Step-by-step tutorial
- [ZeroMemory](/docs/zeromemory/overview) -- Persistent memory for AI
- [API Reference](/docs/api/overview) -- REST API documentation
