You can use Jitsi Meet API to create Jitsi Meet video conferences with a custom GUI. In this article, we will discuss the implementation of chat feature with Jitsi Meet API.

You have to structure your project under two main topics as the development of UI, and its functionality.

Basically the UI is a combination of an input field, a button to submit, and a nice container to show the message history. We also can add an additional option where we can select a participant so that we can send private messages.

Then we can join the sendMessage function, which does the heavy work for us, with the submit button. Also keep in mind that we use an array of objects named messages to store the messages.

The first thing we do within the sendMessage function is to check whether this is a private message or a public message.

If it is public, we can use Jitsi method sendTextMessage(message) that sends the given string to other participants in the conference.

If it is private, we can use Jitsi method sendPrivateTextMessage(privateMessageRecipientId, message) and in turns it send this message to selected participant.
Then we can use the persistSentPrivateMessage function, that push the sent message details in to the messages array.

const sendMessage = async (message) => {

    const privateMessageRecipient = privateMessageRecipientId;   ###put your recipient id

    if (privateMessageRecipientId) {
        room.sendPrivateTextMessage(privateMessageRecipientId, message);
        persistSentPrivateMessage(message);
    } else {
        room.sendTextMessage(message);
    }
};
const persistSentPrivateMessage = (message) => {
    messages.push({
            displayName         ###put your local Participant display name,
            id:                 ###put your local Participant id,
            message
            timestamp,
    }));
}

Then we want to use the conference events that are fired when receive a message, so that the participants can retrieve the sent message.

If the sent message is public then the event that is fired is MESSAGE_RECEIVED, or if it is a private message, then the event is PRIVATE_MESSAGE_RECEIVED.

HandleRecivedMessage function has to be called inside each event, where we can do the processing of received message.

room.on(
    JitsiMeetJS.events.conference.PRIVATE_MESSAGE_RECEIVED,
    (id, message, timestamp) => {
        handleReceivedMessage({
            id,
            message,
            timestamp
        });
    }
);

room.on(
    JitsiMeetJS.events.conference.MESSAGE_RECEIVED,
    (id, message, timestamp) => {
        handleReceivedMessage({
            id,
            message,
            timestamp
        });
    }
);

Inside this handleReceivedMessage function, we reformat the received data from events and push it to messages array for later use.

const handleReceivedMessage = (
    { id, message, timestamp }) => {
    messages.push({
        displayName,
        id,
        message,
        timestamp,
    }));
}

Then the array of messages is listed under the message container to have a nice message history.