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]
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:
npm ci
npm run devWhy: 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]
<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:
- Loading: the application has requested the embed.
- API ready: the wrapper has initialized its External API reference.
- Conference joined: the embedded meeting has emitted that event.
- 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
npm run build
npm run previewThe 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
- [S1] Our downloadable example above, exact lockfile and build receipt reviewed 30 October 2026. No live meeting or browser lifecycle was tested.
- [S2] Official SDK documentation, SDK 1.4.4 package metadata and pinned JitsiMeeting implementation: props, loading and lifecycle behavior.
- [S3] Official IFrame events: listener API and conference event boundaries.
- [S4] Vite guide and Vite 8.3.5 package metadata: development/build commands and engine requirements.
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.