For AI agents: Find a documentation index at https://talkjs.com/llms.txt (full content at https://talkjs.com/llms-full.txt). Get a markdown version of any page by appending .md to its URL path.
Skip to content

Next.js

Next.js chat app components for messaging between users

A Next.js chat app is either an AI chatbot or chat between your users. TalkJS is for the second kind. You get React chat components and the backend that stores and delivers every message. Load the chat only in the browser, through a dynamic import. On Next.js 16 this builds with the default settings and keeps the chat’s 317 kB of JavaScript off the first page load.

'use client';
// app/messages/ChatLoader.tsx
import dynamic from 'next/dynamic';

const Chat = dynamic(() => import('./Chat'), {
  ssr: false,
});

export default function ChatLoader() {
  return <Chat />;
}
Dev A
Hey, I’m trying to lift state up from a child component, but I’m getting undefined errors. Any ideas?
8m ago
You
Are you passing the state and the setState function correctly as props?
6m ago
Dev A
I think so, yes.
5m ago
ok-hand
thinking
You
Maybe you’re not binding the handler in the constructor. That might be the issue.
2m ago
Dev A
typing...
just now
Write a reply...
You
Hi! Is the road bike still for sale?
5m ago
Maya
Yes, it is. I can send more photos of the frame if you like.
4m ago
thumbs-up
You
Please do. Could I pick it up on Saturday?
3m ago
Maya
Saturday works. I’m home after 10.
just now
Great, see you then!
Classtime
Decathlon
Riot Games
Hyundai

Which Next.js chat component fits chat between your users?

One that comes with a backend. A chat component for an AI chatbot shows a model’s reply as it streams in. Chat between people needs more behind the component: every message stored, delivered to the other person in real time, and still reaching them by email or push when they’re offline.

The TalkJS Chatbox, Inbox, and ConversationList components come with that backend, and every plan includes email and mobile push notifications, SMS (charged separately), and moderation tools. Once you launch, you pay per monthly active user: Basic is $279 a month ($239 billed annually) for 10,000 users.

Add chat to your Next.js app with a dynamic import

Install the TalkJS React components and the JavaScript Data API:

npm install @talkjs/react-components @talkjs/core

Put the chat in a Client Component of its own. This is the Chatbox from the Next.js getting started guide, showing a sample conversation from your test mode:

// app/messages/Chat.tsx
'use client';

import { Chatbox } from '@talkjs/react-components';
import '@talkjs/react-components/default.css';

export default function Chat() {
  return (
    <Chatbox
      style={{ width: '400px', height: '600px' }}
      appId="<APP_ID>"
      userId="sample_user_alice"
      conversationId="sample_conversation"
    />
  );
}

Then load it from a second, small Client Component with next/dynamic and ssr: false. Next.js doesn’t allow ssr: false in a Server Component (the build stops with “ssr: false is not allowed with next/dynamic in Server Components”), so your page imports the loader, not the chat:

// app/messages/ChatLoader.tsx
'use client';

import dynamic from 'next/dynamic';

const Chat = dynamic(() => import('./Chat'), { ssr: false });

export default function ChatLoader() {
  return <Chat />;
}
// app/messages/page.tsx (a Server Component)
import ChatLoader from './ChatLoader';

export default function MessagesPage() {
  return (
    <main>
      <h1>Messages</h1>
      <ChatLoader />
    </main>
  );
}

Where each file runs

  1. 1. Serverpage.tsxRenders the page’s HTML, with an empty spot for the chat
  2. 2. Server and browserChatLoader.tsxLoads with the page and asks for the chat with a dynamic import
  3. 3. Browser, after the pageChat.tsxArrives in its own chunk and connects to TalkJS
The three files from the example above, in a Next.js 16.4.4 App Router app.

Why not render the chat straight from the page?

create-next-app 16.4.4 turns on Cache Components in next.config.ts. With it on, a page that renders the chat directly works in next dev, but next build stops with “did not produce a static shell and Next.js was unable to determine a reason”. Wrapping the chat in <Suspense> fixes the build, but the chat’s JavaScript still loads with the page. The loader above fixes both.

How much JavaScript a Next.js 16 page loads with each way of adding the chat

Initial page loadChat loaded later
Page with no chat
Page with no chat: 175 kB on first load175 kB on first load
Chat inside <Suspense>
Chat inside <Suspense>: 493 kB on first load493 kB on first load
Dynamic import (loader)
Dynamic import (loader): 177 kB on first load, then 317 kB for the chat177 kB on first load, then 317 kB for the chat
Gzipped JavaScript from one next build: Next.js 16.4.4 with Cache Components on, React 19.3.0, @talkjs/react-components 0.3.12, November 2026.

Search engines lose nothing either way: even rendered on the server, the chat is an empty container in the page’s HTML.

Next.js chat API: sign user tokens in a route handler

Before you go live, turn on authentication so that only your users can open their chats. Your server signs a token for the signed-in user, and the chat sends it when it connects. In the App Router that’s a Route Handler. This one uses jose to sign the token with the claims listed in the authentication docs:

// app/api/talkjs-token/route.ts
import { SignJWT } from 'jose';
import { getCurrentUserId } from '@/lib/auth'; // your own session lookup

export async function GET() {
  const userId = await getCurrentUserId();
  if (!userId) {
    return Response.json({ error: 'Not signed in' }, { status: 401 });
  }

  const secret = new TextEncoder().encode(process.env.TALKJS_SECRET_KEY);
  const token = await new SignJWT({ tokenType: 'user' })
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuer(process.env.NEXT_PUBLIC_TALKJS_APP_ID!)
    .setSubject(userId)
    .setExpirationTime('1d')
    .sign(secret);

  return Response.json({ token });
}

Take the user ID from your session, never from the request, or anyone could ask for anyone’s token. In the chat component, fetch the token and register it before the chat mounts with getTalkSession({ appId, userId }).setToken(token). Then turn on Authentication (identity verification) in the security settings on the Settings page of your dashboard.

Retreat Guru logo
We were able to offload all messaging to TalkJS — hugely simplifying our development of an otherwise complex stack.
Deryk Wenaus
CTO, Retreat Guru

Next.js chat UI kit you can customize

You style the pre-built chat UIs with properties, CSS, or a custom theme, as the customization guide shows. Need a chat popup? Show a Chatbox when the user clicks a button of your own.

Inbox

The TalkJS Inbox shows the chat history on the left, selected conversation on the right. It’s designed to act as the messaging center of your app, usually living on its own page.

Chatbox

The TalkJS Chatbox is the right half of the Inbox UI mode. It takes up less space and is designed to be embedded in your app near an order confirmation, a booking, or user profile.

Conversation list

The user’s conversations in one list. Put a Chatbox next to it to open the one they pick, or use the Inbox, which combines the two.

FAQs

Yes. TalkJS runs in the browser, so the chat goes in a Client Component with 'use client' at the top, and your pages load it through a small client loader with next/dynamic and ssr: false, as shown above.

Yes. Import the Chatbox straight into a Pages Router page. Its JavaScript then loads with the page, so if you’d rather load it after, use next/dynamic with ssr: false.

Connect your own AI agent with webhooks and the REST API. A webhook notifies your server when a user sends a message, your agent generates a reply, and the REST API sends it back into the conversation. TalkJS doesn’t include its own AI agent, so you choose the model.

TalkJS is free in development mode with full feature access. You only need a paid plan once you go live with real users. See Pricing for details.

Yes. Paste “Add TalkJS chat to my app: talkjs.com/SKILL.md” into your coding agent. Or follow the Next.js getting started guide to set it up yourself.