# Next.js video conferencing app with the Zoom Video SDK - **Update: February 18, 2026** The blog now uses the [Zoom Video SDK for React](https://www.npmjs.com/package/@zoom/videosdk-react) (`@zoom/videosdk-react`) for a simpler React integration. - **Update: April 10, 2025** The blog has been updated to support Next.js v15. The [Zoom Video SDK](/docs/video-sdk/) provides video, audio, screen sharing, chat, and more with an easy to use SDK. In this blog we'll showcase adding video chat to a Next.js web application. This blog will cover both generating JSON Web Tokens (JWTs) on the server-side to authenticate a video session and building the video chat interface using the Zoom Video SDK for React. If you're building a React application without Next.js, you can skip to the [Build the Videochat component](#step-5-build-the-videochat-component) section and use your own JWT generation logic. A demo built with React & Vite is available on [GitHub](https://github.com/zoom/VideoSDK-React-Quickstart/). For this blog, we’ll use the [app router](https://nextjs.org/docs#app-router-vs-pages-router). You can find the code on [GitHub](https://github.com/zoom/VideoSDK-Nextjs-Quickstart/). A demo with the pages router is also available on the [pages-router branch](https://github.com/zoom/videosdk-nextjs-quickstart/tree/pages-router). ### Prerequisites: - Node LTS & NPM - A Zoom [Video SDK Account](/docs/video-sdk/get-credentials/) ## Step 1: Scaffold the application If you already have a Next.js project, you can skip this step. To scaffold our application we'll be using [Next.js CLI](https://nextjs.org/docs/getting-started/installation#automatic-installation). Open a terminal and execute: ```bash npx create-next-app@latest ``` Go ahead and select the config you like, we chose most of the defaults: ```bash What is your project named? videosdk-nextjs-quickstart Would you like to use TypeScript? Yes Would you like to use ESLint? Yes Would you like to use Tailwind CSS? Yes Would you like to use `src/` directory? Yes Would you like to use App Router? (recommended) Yes Would you like to customize the default import alias (@/*)? No ``` ## Step 2: Configuring the project ### Install the dependencies We will install the [Zoom Video SDK for Web](https://www.npmjs.com/package/@zoom/videosdk) (`@zoom/videosdk`), the [Zoom Video SDK for React](https://www.npmjs.com/package/@zoom/videosdk-react) (`@zoom/videosdk-react`), [jsrsasign](https://www.npmjs.com/package/jsrsasign) to generate JWTs, and [server-only](https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment) to keep server-only code out of the client bundle. You can use the following command for installation: ```bash npm install @zoom/videosdk @zoom/videosdk-react jsrsasign server-only ``` ### Script to enable shared array buffers To leverage the full power of the Zoom Video SDK—including features like rendering multiple videos, virtual background, and background noise suppression—we need to enable support for Shared Array Buffers (SAB). Simply download this [file](https://github.com/gzuidhof/coi-serviceworker/blob/master/coi-serviceworker.js) and place it in the `public` folder of your project as `public/coi-serviceworker.js`. Later, we’ll import this file to enable SAB support. You can read more about SAB [in our documentation](/docs/meeting-sdk/web/sharedarraybuffer/). ### Add Environment Variables To complete the setup, create a `.env` file in the root of our project and add the Zoom Video SDK Key and Secret to it. You can find your SDK Key and Secret in the [Video SDK Dashboard](https://marketplace.zoom.us), by clicking on the _Develop_ button and selecting _Build Video SDK_. Make sure you're logged in to your Video SDK account. ```bash ZOOM_SDK_KEY="Your Zoom SDK Key" ZOOM_SDK_SECRET="Your Zoom SDK Secret" ``` ## Step 3: Authenticate a session The Zoom Video SDK uses JWTs to authenticate a session. We can define a function `getData` in `/src/data/getToken.ts` to generate a JWT based on the session slug. Creating a JWT requires the SDK Key and Secret. We'll import [`server-only`](https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment) to make sure this function will only be executed on the server, keeping our SDK key and secret secure. This will create a JWT using the `generateSignature` function and return it. ```ts import "server-only"; export async function getData(slug: string) { const JWT = await generateSignature(slug, 1); return JWT; } ``` The `generateSignature` function will use the `jsrsasign` library and the session name to generate the JWT: ```ts import { KJUR } from "jsrsasign"; function generateSignature(sessionName: string, role: number) { if (!process.env.ZOOM_SDK_KEY || !process.env.ZOOM_SDK_SECRET) { throw new Error("Missing ZOOM_SDK_KEY or ZOOM_SDK_SECRET"); } const iat = Math.round(new Date().getTime() / 1000) - 30; const exp = iat + 60 * 60 * 2; const oHeader = { alg: "HS256", typ: "JWT" }; const sdkKey = process.env.ZOOM_SDK_KEY; const sdkSecret = process.env.ZOOM_SDK_SECRET; const oPayload = { app_key: sdkKey, tpc: sessionName, role_type: role, version: 1, iat: iat, exp: exp, }; const sHeader = JSON.stringify(oHeader); const sPayload = JSON.stringify(oPayload); const sdkJWT = KJUR.jws.JWS.sign("HS256", sHeader, sPayload, sdkSecret); return sdkJWT; } ``` ## Step 4: Dynamic route for video chat We'll create a [Server Component](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#fetching-data-on-the-server-with-fetch) at the `/call/` [dynamic route](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes). We can use this to create a link for each session based on user input. Users on the same link will be able to join the same session. We can import and call the `getData` function to obtain a JWT and use it within the `Page` component in `/src/call/[slug]/page.tsx`. ```ts import { getData } from "@/data/getToken"; export default async function Page({ params }: { params: { slug: string } }) { const jwt = await getData(params.slug); return (
); } ``` We add a `Script` tag from [`next/script`](https://nextjs.org/docs/pages/building-your-application/optimizing/scripts#application-scripts) and import the `coi-serviceworker.js` file we added earlier. We'll also add a [client component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) `VideochatClientWrapper` that will dynamically load and render the video chat UI (which uses `@zoom/videosdk-react`). ```ts import { getData } from "@/data/getToken"; import VideochatClientWrapper from "@/components/VideochatClientWrapper"; import Script from "next/script"; export default async function Page(props: { params: Promise<{ slug: string }> }) { const params = await props.params; const jwt = await getData(params.slug); return (