Add Jitsi to a small React app, one stage at a time

Short answer

Use JitsiMeeting to embed an existing Jitsi service in a React app. Our downloadable example collects the server and room first, opens the embed on request, distinguishes API readiness from conference joining and disposes the API when closing. Its production build was verified; browser interaction and real meeting media were not tested. [S1][S2]

The result and its limits

You will build a small React page with three fields: a meeting-server hostname, a test room and a display name. Submitting the form mounts the meeting embed. A status message distinguishes loading, API readiness and conference joining. A Close embed button disposes the API and returns to the form. This is our original example, not a copy of the handbook demo. [S1][S2]

The versions checked on 30 October 2026 are React/React DOM 19.3.1, @jitsi/react-sdk 1.4.4 and Vite 8.3.5. The recorded production build used Node 22.23.4. Vite’s package declares Node ^20.19.0 || >=22.12.0; this example selects the Node 22 line. Exact dependencies and a lockfile are included. These pins identify the reviewed example, not a promise that they stay the newest versions. [S1][S4]

No actual browser join, permission prompt, microphone/camera, navigation lifecycle or two-party media test was completed. Browser control was unavailable during authoring. Build success is the verified result; the checks below describe what you should verify on your own service.

1. Download the complete example

Download the React example source ZIP, extract it, and open the jitsi-react-sdk folder in a terminal. The archive contains source and the lockfile, not installed dependencies or a compiled application. [S1]

Text
jitsi-react-sdk/
  package.json
  package-lock.json
  index.html
  README.md
  src/
    main.jsx
    App.jsx
    style.css
File What to understand first
package.json and lockfile Exact dependencies and development/build commands.
index.html The root element and entry script.
src/main.jsx Mounts the React application.
src/App.jsx Form, embed lifecycle, status messages and cleanup.
src/style.css Small standalone styles; no dependency on jitsi.help’s site theme.

Check: start in the folder that contains package.json. Read the README and verify that your selected service permits your intended embedding and testing. The example starts on a local form; it does not silently join a public room.

2. Install and run the browser application

From the extracted example folder:

Terminal
npm ci
npm run dev

Why: npm ci uses the supplied lockfile. Vite supplies the development page. [S1][S4]

Check: open the localhost address printed by Vite and expect the input form. No meeting is created by compiling the project. If installation fails, check your Node version, package registry access and whether you are in the correct folder before changing Jitsi configuration.

The development command binds to 127.0.0.1. It is a local learning app, not a deployment instruction for a public server. Production hosting and its HTTPS requirements are a separate task. [S1][S4]

3. Enter a service, a room and a display name

Use the hostname of a service you are authorized to access, such as your own meet.example.com. The form expects the hostname only, without https:// or a path. The placeholder is an example domain, not a working test server. Choose a new room you are authorized to use and a suitable display name. [S1]

Why: the SDK’s domain selects the service that supplies the External API. A room name identifies the meeting within that service. userInfo.displayName supplies display information; it is not proof of authentication. JitsiMeeting and JaaSMeeting are different SDK entry points; this example uses the former with an explicitly chosen domain. [S2]

Check: select Open meeting embed and follow the chosen service’s join, login or admission flow. Private services can require their own integration setup. For meet.jit.si, check its current service policies; embedding does not remove them. Use the login guide for access questions.

4. Understand the readiness boundaries

This excerpt is from the complete App.jsx; surrounding form and cleanup code are in the download. [S1][S2][S3]

jsx
<JitsiMeeting
  domain={meeting.domain}
  roomName={meeting.roomName}
  userInfo={{ displayName: meeting.displayName }}
  configOverwrite={{ startWithAudioMuted: true, startWithVideoMuted: true }}
  onApiReady={(api) => {
    apiRef.current = api;
    setStatus('Meeting API ready. Complete the service join flow.');
    api.addListener('videoConferenceJoined', () => {
      setStatus('Conference joined. Verify audio and video with a consenting attendee.');
    });
  }}
  onReadyToClose={closeMeeting}
  getIFrameRef={(container) => { container.style.height = 'min(70vh, 720px)'; }}
/>

Read the statuses in order:

  1. Loading: the application has requested the embed.
  2. API ready: the wrapper has initialized its External API reference.
  3. Conference joined: the embedded meeting has emitted that event.
  4. Media received: another attendee confirms actual reception. The example does not measure this fourth result automatically. [S1][S2][S3]

startWithAudioMuted and startWithVideoMuted are starting preferences, not guarantees about permission prompts, remote delivery or authorization. Check the client’s actual state before a test. For more commands and event handling, use the existing IFrame API guide.

5. Close the embed deliberately

The inspected SDK 1.4.4 component creates the External API but does not include a disposal effect for component unmount. Our example owns that cleanup. It clears its stored reference, calls dispose() on the existing API and removes the meeting component. An application-unmount cleanup also disposes a stored API. These are source-reviewed implementation choices; their browser behavior still needs testing. [S1][S2]

Check: close after API readiness, then open another test room. Also check your real application’s navigation/unmount path. Confirm that the previous iframe and meeting participation end, and that another embed can open. Closing a frame is not a recording-retention policy or an account deletion operation.

6. Build and verify the result

Terminal
npm run build
npm run preview

The production build was completed during review. Preview serves its output locally for your checks. Verify the form, loading status, API-ready boundary, join event, close action and a fresh second embed. Then use consenting attendees to check audio/video in both directions, including your service’s authentication and actual network conditions. [S1][S4]

Diagnose by stage

Observation First useful check
The form never appears Folder, dependency installation, Vite output and local console.
Form appears, but API readiness never arrives The chosen domain, its external_api.js, script/network errors, embedding policy and actual service availability. [S2]
API is ready but the meeting is not joined Service login, room/access rules and join UI; readiness does not bypass admission.
Conference joins but no one receives media Mute/device state, permission and the service’s media path, not simply the SDK import.
Old room remains after navigation Verify explicit disposal and unmount in your application; compare the pinned example before altering the SDK. [S1][S2]

This page does not prescribe an untested window is not defined fix. It is a Vite client app, not a Next.js server-rendering example. If you use another framework, reproduce its execution boundary and consult that framework’s current documentation before adding a workaround.

The example contains no JWT signer. If your service needs issued tokens, add that flow through an authorized backend and follow the JWT guide. Never put a signing secret or provider credentials in a browser bundle.

Sources and maintenance

Recheck the lockfile, SDK loading/disposal behavior and your service’s API after upgrades. Open questions are your actual authentication setup, browser behavior, readiness failures and successful two-party media on the intended networks.

Written by the Jitsi Help engineering team

Jitsi infrastructure engineers who deploy and run Jitsi Meet servers in production. Last updated . How we write our guides

Stuck on something this page does not cover? Ask a question below. Jitsi Help engineers read every one.

Did this guide work for you?

Something on this page is outdated or wrong?

Frequently asked questions

Does this example create a Jitsi server?

No. The React app embeds a meeting service you choose. That service still controls availability, authentication, admission and feature configuration. Hosting the frontend does not provision a meeting backend.

Does onApiReady mean I have joined the conference?

No. The example treats the API-ready callback and videoConferenceJoined event as different boundaries. Neither proves that a second attendee receives your microphone or camera. Verify media separately in an authorized test meeting.

Can I paste this Vite example into Next.js unchanged?

This recipe is for a browser application built with Vite. A server-rendered framework has different execution and lifecycle boundaries. No Next.js or SSR recipe was tested here; establish that framework's browser-side boundary before integrating the meeting SDK.

Where should I put my JWT signing secret?

Keep signing secrets on an authorized backend. This example contains no signer or token-generation endpoint. A browser may receive an appropriate issued token for a configured service, but it must not contain the secret that signs tokens.

Discussion

    Stuck, or would rather not do this by hand?

    Deploy it in one click

    A private Jitsi server in your own AWS account with SSL, your domain and optional recording, transcription and JWT. Free 15 minute trial.

    Start free trial

    Talk to a Jitsi engineer

    Setup, fixes, branding, recording, scaling. Tell us what is happening and we reply with a plan and a quote.

    Get expert help

    Related

    Recently updated