Mastering the Huddle01 SDK - 8 tips to keep in mind
Important tips and tricks to take a note of while working with the Huddle01 SDK and adding live audio/video to your app.
While working on the Huddle01 SDK and incorporating feedback from our developer community, I also collated a few helpful tips and tricks for building with the Huddle01 SDK to make the development process easier and faster for you.
Most of the information I'll be sharing in this blog post is especially relevant for Next JS. Although you can apply the same concepts in React, keep in mind that server-side rendering is not possible with React alone.
So, without further ado, let's dive in and get started 🚀
1. Stay up-to-date with the latest SDK version
We regularly update our SDKs to provide the best developer experience possible. Therefore, I highly recommend checking if you have the latest version of the Huddle01 SDK installed. If you don't you can easily upgrade it by running the following command.
pnpm update @huddle01/react@latest
2. Call APIs from the server side
Whenever you need to use APIs such as create-room
, live-meetings
, get-rooms
, etc., it is always recommended to make the API calls from the server side instead of the client side. Calling these APIs from the client side may pose a risk of exposing your PRIVATE_KEY
. If you are using Next JS, you can make the API calls from getServerSideProps
or create an API route using a Serverless function.
createRoom.ts
// Next.js API route support: <https://nextjs.org/docs/api-routes/introduction>
import type { NextApiRequest, NextApiResponse } from "next";
interface RoomDetails {
message: string;
data?: {
roomId: string;
};
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const response = await fetch("<https://api.huddle01.com/api/v1/create-room>", {
method: "POST",
body: JSON.stringify({
title: req.body.title,
startTime: req.body.startTime,
hostWallets: req.body.hostWallets
}),
}),
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.API_KEY as string,
},
});
const data: RoomDetails = await response.json();
res.status(200).json({ roomId: data?.data?.roomId });
}
Make sure to store your API_KEY in the .env file and add it to the .gitignore to prevent it from being exposed. If you are using the App router in Next JS, there is no need to use a Serverless function. Instead, you can simply create a new server-side component that calls this API and returns the roomId.
3. Using useEventListener
to handle events
In general, we typically use the useEffect
hook and check the state to see if it has changed. However, in our SDKs, we provide a built-in event listener that allows you to listen to various events such as room:joined
, room:peer-left
, app:cam-on
, app:mic-on
, and more. You can find more information about the supported events here. The useEventListener
function will be particularly useful when you want to set up your current video stream or perform certain actions on certain events.
import { useEventListener } from "@huddle01/react/hooks"
...
useEventListener("room:joined", () => {
// Write you logic here on lobby joined
}
...
4. Displaying your viewport
Many builders who use our SDK encounter issues when trying to display their viewport after fetching a video stream. To display your viewport, you need to create a videoRef
and set it with the stream obtained from calling fetchVideoStream
.
import { useVideo, useEventListener } from "huddle01/react/hooks";
import { useEffect, useRef } from 'react';
...
const { fetchVideoStream } = useVideo();
useEventListener("app:cam-on", (stream) => {
if (stream && videoRef.current) {
videoRef.current.srcObject = stream;
}
});
...
// jsx
<>
<video ref={videoRef} autoPlay />
<button onClick={fetchVideoStream}> fetch video </button>
</>
...
Here, when you click on fetchVideo
, it will call the fetchVideoStream
method and trigger the app:cam-on
event. This event returns the stream that we can use to set videoRef
.
5. Showing peers' viewport
Displaying the viewport of other peers (participants) in the room is straightforward using ready-to-use components from our SDK. Our SDK provides two components: one for video and one for audio.
import { Video, Audio } from "@huddle01/react/components";
import { usePeers } from "@huddle01/react/hooks";
const { peers } = usePeers();
...
//jsx
Object.values(peers).map(({ peerId, cam, mic }) => (
<>
{cam && (
<Video key={peerId} track={cam} peerId={peerId} />
)}
{mic && (
<Audio key={peerId} track={mic} peerId={peerId} />
)}
</>
)
)}
...
6. Managing routes for Lobby and Room
When joining a room, it is recommended to follow a proper flow by creating two separate pages: one for the lobby and another for the room. In the lobby, users can set their avatar and display name. The files should be organized as follows:
pages
[roomId]
lobby.tsx (This page is for the Lobby)
index.tsx (This page is for the Room)
When a user navigates to {url}/[roomId]
, we first check if the room has been joined or not using the isRoomJoined
variable obtained from the useRoom
hook. If isRoomJoined
is false, the user will be redirected to {url}/[roomId]/lobby
.
import { useRoom } from "@huddle01/react/hooks";
import { useRouter } from "next/router";
const { isRoomJoined } = useRoom();
const { query } = useRouter();
useEffect(() => {
if (!isRoomJoined && query.roomId) {
push(`/${query.roomId}/lobby`);
return;
}
}, [isRoomJoined, query.roomId]);
7. Switching media devices
Our SDK provides built-in methods to retrieve a list of available media devices. The useVideo
and useAudio
functions include the enumerateCamDevices
and enumerateMicDevices
hooks, respectively, which return lists of available camera and audio devices. Once you have obtained this list, you can display it in a dropdown menu and prompt the user to select a device. After the user has made a selection, you can retrieve the deviceId of the chosen device and pass it as an argument to the fetchVideoStream
and fetchAudioStream
methods.
import { useVideo, useAudio } from "@huddle01/react/hooks";
import { useEffect } from "react";
const { fetchVideoStream, enumerateCamDevices, camDevices } = useVideo();
const { fetchAudioStream, enumerateMicDevices, micDevices } = useAudio();
useEffect(() => {
enumerateCamDevices();
enumerateMicDevices();
}, [])
...
// jsx
<>
<button onClick={() => fetchVideoStream(camDevices[0].deviceId)} fetch video <button/>
<button onClick={() => fetchAudioStream(micDevices[0].deviceId)} fetch audio <button/>
</>
...
8. Sending Data to Peers
You can send any type of text-based data to all peers in the room. This functionality is useful for implementing features like sending reactions, speaker requests, and more. One cool feature that you can implement using the sendData
function from our SDK is chat. You can create your chat UI and utilise the sendData
function to send messages. The best part is that you can even send data to specific peers by passing an array of peerIds
.
import { useAppUtils } from "@huddle01/react/app-utils";
import { useEventListener } from "@huddle01/react/hooks";
const { sendData } = useAppUtils();
// listen to receive data event and get data from it
useEventListener("room:data-received", (data) => {
console.log(data);
});
const sendReaction = (emoji) => {
// Here "*" represents all peers in the room
sendData("*", {emoji: emoji });
};
const sendMessage = (peerId: string) => {
// Send data to specific peer
sendData(peerId, { message: "Hello World!"} );
};
Happy Hacking ⚒️
Thank you so much for taking the time to read this article! 😊 I hope you've enjoyed it and have learned something new. I'm excited to see what amazing projects you'll build using the Huddle01 SDKs. If you have any questions or need assistance, feel free to reach out to us on our Discord. We're here to help you 24/7. And don't forget to check out our docs for even more information about our SDKs.
Happy coding! 💻👨💻