Next.js 12 Quickstart

Get started with LiveKit and Next.js 12

1. Install LiveKit SDK

Install the LiveKit SDKs for the server and client:

yarn add livekit-server-sdk @livekit/components-react @livekit/components-styles

2. Keys and Configuration

To start, your app needs an LiveKit API key and secret, as well as your LiveKit project URL.

Create a new file at .env.development.local with the following contents. Do not commit this file!

LIVEKIT_API_KEY=<your API Key>
LIVEKIT_API_SECRET=<your API Secret>
NEXT_PUBLIC_LIVEKIT_URL=<your LiveKit server URL>

3. Create token endpoint

Create a new file at /api/get_lk_token.ts with the following contents:

import { AccessToken } from "livekit-server-sdk";
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const room = req.query.room as string;
const username = req.query.username as string;
if (req.method !== "GET") {
return res.status(400).json({ error: "Invalid method" });
} else if (!room) {
return res.status(400).json({ error: 'Missing "room" query parameter' });
} else if (!username) {
return res.status(400).json({ error: 'Missing "username" query parameter' });
}
const apiKey = process.env.LIVEKIT_API_KEY;
const apiSecret = process.env.LIVEKIT_API_SECRET;
const wsUrl = process.env.NEXT_PUBLIC_LIVEKIT_URL;
if (!apiKey || !apiSecret || !wsUrl) {
return res.status(500).json({ error: "Server misconfigured" });
}
const at = new AccessToken(apiKey, apiSecret, { identity: username });
at.addGrant({ room, roomJoin: true, canPublish: true, canSubscribe: true });
res.status(200).json({ token: await at.toJwt() });
}

4. Make a page in your web app

Make a new file at /pages/room.tsx with the following contents:

import '@livekit/components-styles';
import {
LiveKitRoom,
VideoConference,
GridLayout,
ParticipantTile,
} from '@livekit/components-react';
import { Track } from 'livekit-client';
import { useEffect, useState } from 'react';
export default () => {
// TODO: get user input for room and name
const room = 'quickstart-room';
const name = 'quickstart-user';
const [token, setToken] = useState('');
useEffect(() => {
(async () => {
const resp = await fetch(`/api/get_lk_token?room=${room}&username=${name}`);
const data = await resp.json();
setToken(data.token);
})();
}, []);
if (token === '') {
return <div>Getting token...</div>;
}
return (
<LiveKitRoom
video={true}
audio={true}
token={token}
serverUrl={process.env.NEXT_PUBLIC_LIVEKIT_URL}
// Use the default LiveKit theme for nice styles.
data-lk-theme="default"
style={{ height: '100dvh' }}
>
{/* Your custom component with basic video conferencing functionality. */}
<MyVideoConference />
{/* The RoomAudioRenderer takes care of room-wide audio for you. */}
<RoomAudioRenderer />
{/* Controls for the user to start/stop audio, video, and screen
share tracks and to leave the room. */}
<ControlBar />
</LiveKitRoom>
);
}
function MyVideoConference() {
// `useTracks` returns all camera and screen share tracks. If a user
// joins without a published camera track, a placeholder track is returned.
const tracks = useTracks(
[
{ source: Track.Source.Camera, withPlaceholder: true },
{ source: Track.Source.ScreenShare, withPlaceholder: false },
],
{ onlySubscribed: false },
);
return (
<GridLayout tracks={tracks} style={{ height: 'calc(100vh - var(--lk-control-bar-height))' }}>
{/* The GridLayout accepts zero or one child. The child is used
as a template to render all passed in tracks. */}
<ParticipantTile />
</GridLayout>
);
}

5. Load the page and connect

Start your server with:

yarn dev

And then open localhost:8000/room in your browser.

6. Next Steps

If you're looking to dive deeper into building your LiveKit app with React, check out the React Components reference section. There you'll find a comprehensive list of available components and React hooks, along with examples of how to use them. This is a great resource for building more complex and advanced apps. Happy coding!