Skip to main content

Next.js

Next.js is a React web development framework. When used with Convex, Next.js provides:

  • File-system based routing
  • Fast refresh in development
  • Font and image optimization

and more!

This pages covers the App Router variant of Next.js. Alternatively see the Pages Router version of this page.

Getting started

Follow the Next.js Quickstart to add Convex to a new or existing Next.js project.

Adding client-side authentication

The simplest approach to authentication in Next.js is to keep it client-side.

For example Auth0 describes this approach in Next.js Authentication with Auth0 guide, describing it in "Next.js Static Site Approach" and "Serverless with the user on the frontend".

To require login on every page of your application you can add logic to app/ConvexClientProvider.tsx to conditionally render page content, blocking it until the user is logged in.

If you're using Auth0, the helper component ConvexProviderWithAuth0 can be imported from convex/react-auth0.

app/ConvexClientProvider.tsx
"use client";

import { ReactNode } from "react";
import { ConvexReactClient } from "convex/react";
import { ConvexProviderWithAuth0 } from "convex/react-auth0";
import { Auth0Provider } from "@auth0/auth0-react";

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export default function ConvexClientProvider({
children,
}: {
children: ReactNode;
}) {
return (
<Auth0Provider
domain={process.env.NEXT_PUBLIC_AUTH0_DOMAIN!}
clientId={process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID!}
authorizationParams={{
redirect_uri:
typeof window === "undefined" ? undefined : window.location.origin,
}}
useRefreshTokens={true}
cacheLocation="localstorage"
>
<ConvexProviderWithAuth0 client={convex}>
{children}
</ConvexProviderWithAuth0>
</Auth0Provider>
);
}

Custom loading and logged out views can be built with the helper Authenticated, Unauthenticated and AuthLoading components from convex/react, see the Convex Next.js demo for an example.

If only some routes of your app require login, the same helpers can be used directly in page components that do require login instead of being shared between all pages from app/ConvexClientProvider.tsx. Share a single ConvexReactClient instance between pages to avoid needing to reconnect to Convex on client-side page navigation.

Read more about authenticating users with Convex in Authentication.

Route Handlers

Next.js supports building HTTP request handling routes, similar to Convex HTTP Actions. Using Next.js routes might be helpful if you need to use a dependency not supported by the Convex default runtime.

To build a Route Handler add route.js|ts file to the your app directory.

To load and edit Convex data in your route handler, you can use the ConvexHttpClient to call your query and mutation functions:

app/clicks/route.ts
import { ConvexHttpClient } from "convex/browser";
import { NextResponse } from "next/server";

const convex = new ConvexHttpClient(process.env.NEXT_PUBLIC_CONVEX_URL);

export async function GET(request: Request) {
const clicks = await convex.query(api.counter.get, { counterName: "clicks" });
return NextResponse.json({ clicks });
}

Server-side rendering

We currently recommend client-side rendering Convex data when using Next.js. This is because data from Convex is fully reactive. Convex needs a connection from your deployment to the browser in order to push updates as data changes and that must happen on the client.

If you need Convex data on the server, you can load data from Convex in your Server Components, but it will be non-reactive. To do this, use the ConvexHttpClient to call query functions just like you would in Route Handlers.

To make authenticated requests to Convex during server-side rendering, the ConvexHttpClient instance needs authentication info present server-side. Auth0 describes this approach in Serverless with the user on the backend. When server-side rendering, call ConvexHttpClient.setAuth to fetch the user's identity token before making the query.

We are investigating ways to combine Next.js server-side rendering with end-to-end reactivity. Stay tuned!