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
  • API routes
  • Fast refresh in development
  • Font and image optimization

and more!

Getting Started

You can create a new Next.js app with

npx create-next-app myapp --use-npm --typescript

Then install the Convex client library and initialize a new project.

cd myapp
npm install convex
npx convex login
npx convex init

See quick start for more on these steps and the Basic Concepts section for a more detailed explanation.

Adding the Convex Provider

Next.js routes are defined in the pages/ directory, each file defining the component that runs only on that page. The component in pages/_app.tsx acts as a parent for all pages, persisting through client-side page navigations. This makes pages/_app.tsx an excellent place to add the <ConvexProvider/> wrapper when Convex is used throughout a Next.js app.

pages/_app.tsx
import type { AppProps } from "next/app";

import { ConvexProvider, ConvexReactClient } from "convex/react";
import convexConfig from "../convex.json";
const convex = new ConvexReactClient(convexConfig.origin);

function MyApp({ Component, pageProps }: AppProps) {
return (
<ConvexProvider client={convex}>
<Component {...pageProps} />;
</ConvexProvider>
);
}

export default MyApp;

Adding Client-Side Authentication

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

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.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 after installing the Auth0 React library with npm install @auth0/auth0-react.

pages/_app.tsx
import type { AppProps } from "next/app";

import { ConvexReactClient } from "convex/react";
import { ConvexProviderWithAuth0 } from "convex/react-auth0";
import convexConfig from "../convex.json";

const convex = new ConvexReactClient(convexConfig.origin);
const authInfo = convexConfig.authInfo[0];

export default function MyApp({ Component, pageProps }: AppProps) {
return (
<ConvexProviderWithAuth0 client={convex} authInfo={authInfo}>
<Component {...pageProps} />
</ConvexProviderWithAuth0>
);
}

Custom loading and logged out views can be passed to this component, see the Convex Next.js demo for an example.

If only some routes of your app require login, a similar wrapper could be used directly in page components that do require login instead of being shared between all pages from pages/_app.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 the Users and Auth docs. In particular, be sure to run npx convex auth add to configure Convex for your chosen auth provider.

API Routes

Next.js supports building API routes by adding files to the pages/api directory.

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

pages/api/clicks.ts
import type { NextApiRequest, NextApiResponse } from "next";
import convexConfig from "../../convex.json";
import { ConvexHttpClient } from "convex/browser";

const convex = new ConvexHttpClient(convexConfig.origin);
type Data = {
clicks: number;
};

export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const clicks = await convex.query("getCounter")("clicks");
res.status(200).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 getStaticProps or getServerSideProps, but it will be non-reactive. To do this, use the ConvexHttpClient to call query functions just like you would in API routes.

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 with the user's auth token before making the query.

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