#How do I use convex with Next JS API routes when using app directory?
5 messages · Page 1 of 1 (latest)
Hi @hearty goblet. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
To use Convex with Next.js API routes in the App Router, you'll need to set up your Convex client and create route handlers that can interact with your Convex backend. Here's how to do it:
Files to Make
app/ConvexClientProvider.tsx- Client component for Convex providerapp/layout.tsx- Root layout with Convex providerapp/api/route.ts- API route handlerconvex/tasks.ts- Example Convex function
Sample Code
1. Create a Client Provider Component
First, create a client component that initializes the Convex client:
"use client";
import { ConvexProvider, ConvexReactClient } from "convex/react";
import { ReactNode } from "react";
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
export function ConvexClientProvider({ children }: { children: ReactNode }) {
return <ConvexProvider client={convex}>{children}</ConvexProvider>;
}
2. Set Up Your Root Layout
In your root layout, wrap your application with the Convex provider:
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { ConvexClientProvider } from "./ConvexClientProvider";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<ConvexClientProvider>{children}</ConvexClientProvider>
</body>
</html>
);
}
3. Create an API Route Handler
Create a route handler that uses Convex functions:
import { NextResponse } from "next/server";
// Hack for TypeScript before 5.2
const Response = NextResponse;
import { api } from "@/convex/_generated/api";
import { fetchMutation } from "convex/nextjs";
export async function POST(request: Request) {
const args = await request.json();
await fetchMutation(api.tasks.create, { text: args.text });
return Response.json({ success: true });
}
4. Create a Convex Function
Create a Convex function that your API route will call:
import { mutation } from "./_generated/server";
import { v } from "convex/values";
export const create = mutation({
args: { text: v.string() },
handler: async (ctx, args) => {
return await ctx.db.insert("tasks", {
text: args.text,
isCompleted: false,
});
},
});
Using Server Actions
You can also use Convex with Server Actions in Next.js. Here's an example:
import { api } from "@/convex/_generated/api";
import { fetchMutation, fetchQuery } from "convex/nextjs";
import { revalidatePath } from "next/cache";
export default async function PureServerPage() {
const tasks = await fetchQuery(api.tasks.list, { list: "default" });
async function createTask(formData: FormData) {
"use server";
await fetchMutation(api.tasks.create, {
text: formData.get("text") as string,
});
revalidatePath("/example");
}
// render tasks and task creation form
return <form action={createTask}>...</form>;
}
For authenticated requests, you'll need to pass a JWT token to the Convex functions:
import { preloadQuery } from "convex/nextjs";
import { api } from "@/convex/_generated/api";
export async function TasksWrapper() {
const token = await getAuthToken();
const preloadedTasks = await preloadQuery(
api.tasks.list,
{ list: "default" },
{ token },
);
return <Tasks preloadedTasks={preloadedTasks} />;
}
The implementation of `getAuthToken` depends on your authentication provider (Clerk, Auth0, etc.).
[Next.js Server Rendering](<https://docs.convex.dev/client/react/nextjs/server-rendering#server-actions-and-route-handlers>) provides more details on using Convex with Server Actions and Route Handlers.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------