Clerk
Learn how to integrate Tambo with Clerk for user authentication.
Clerk is a complete authentication and user management solution that handles authentication through middleware without requiring specific API routes. This guide shows how to integrate it with Tambo.
Prerequisites
This guide assumes you've already set up Clerk in your Next.js application, including middleware and sign-in/sign-up pages. If you haven't, follow the Clerk Next.js Quick Start first.
Installation
Install the required packages:
npm install @clerk/nextjs @tambo-ai/react
Integration Options
Server-Side Token Retrieval (Recommended)
Use this approach for better security and performance, especially when you don't need real-time authentication state changes.
import { auth } from "@clerk/nextjs/server";
import ClientLayout from "./client-layout";
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const { getToken } = await auth();
const token = await getToken();
return (
<html lang="en">
<body>
<ClientLayout userToken={token}>{children}</ClientLayout>
</body>
</html>
);
}
"use client";
import { ClerkProvider } from "@clerk/nextjs";
import { TamboProvider } from "@tambo-ai/react";
import { ReactNode } from "react";
interface ClientLayoutProps {
children: ReactNode;
userToken?: string;
}
export default function ClientLayout({
children,
userToken,
}: ClientLayoutProps) {
return (
<ClerkProvider>
<TamboProvider userToken={userToken}>{children}</TamboProvider>
</ClerkProvider>
);
}
Client-Side Token Retrieval
Use this approach when you need real-time authentication state management or client-side routing with authentication guards.
"use client";
import { ClerkProvider } from "@clerk/nextjs";
import ClientLayout from "./client-layout";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<ClerkProvider>
<ClientLayout>{children}</ClientLayout>
</ClerkProvider>
</body>
</html>
);
}
"use client";
import { useAuth } from "@clerk/nextjs";
import { TamboProvider } from "@tambo-ai/react";
import { ReactNode, useEffect, useState } from "react";
interface ClientLayoutProps {
children: ReactNode;
}
export default function ClientLayout({ children }: ClientLayoutProps) {
const { getToken, isLoaded, isSignedIn } = useAuth();
const [accessToken, setAccessToken] = useState<string | undefined>();
useEffect(() => {
async function fetchToken() {
if (isLoaded && isSignedIn) {
try {
const token = await getToken();
setAccessToken(token || undefined);
} catch (error) {
console.error("Error fetching token:", error);
}
}
}
fetchToken();
}, [isLoaded, isSignedIn, getToken]);
return <TamboProvider userToken={accessToken}>{children}</TamboProvider>;
}
Usage
Once configured, you can use Tambo components throughout your application:
import { MessageThreadFull } from "@components/ui/tambo";
export default function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<MessageThreadFull />
</div>
);
}
Advanced Configuration
Custom JWT Templates
For advanced use cases, you can create custom JWT templates in Clerk to include specific claims:
- Go to your Clerk Dashboard
- Navigate to "JWT Templates"
- Create a new template with the claims you need
- Use the template name when calling
getToken()
:
const token = await getToken({ template: "your-template-name" });
Token Format
Clerk provides JWT tokens that include the user's ID in the sub
claim, which
is exactly what Tambo needs for user identification. The token is
automatically signed and verified by Clerk.