Embedded video calls in 5 minutes with repl.it and Daily.co

Here's a demo showing one-click video calls integrated into the UI of a hypothetical collaborative design tool.

Daily.co API demo example

Let's create a similar demo, ourselves, in 3 simple steps. You can probably follow along and add these code snippets to any of your own web pages in just a few minutes.

  1. First, we'll make a “start call” button that adds a video call iframe to a web page.
  2. Second, with repl.it's help, we'll spin up an HTTP function-as-a-service endpoint that creates a new, unique, video call link each time our “start call” button is pressed.
  3. And finally, we'll add a few lines of javascript to make the page URL shareable so that other people can join the call.

If you haven't tried out repl.it yet, it's a cloud development environment and infrastructure platform. You can write interactive code, in your web browser, develop collaboratively, and host full projects and websites with almost no setup overhead. Repl.it supports more than 50 languages. We 💖 it!

Okay, let's build our on-demand video calls demo …

1. A button

We need a way for a user to start a video call. Add the Daily.co javascript library to your page's head, then we'll make a button that creates an iframe and adds it to our web page.

<head>
  <script crossorigin src="https://unpkg.com/@daily-co/daily-js"></script>
</head>
<button onclick="startCall()">
  start call
</button>
<script>
async function startCall() {
  let callUrl = 'https://api-demo.daily.co/this-is-a-placeholder',
    callFrame = window.DailyIframe.createFrame({
      url: callUrl
    });
    callFrame.join();
  }
 </script>

Drop this code into any web page. If you don't have a super-easy way to set up a prototype page, you can just clone this empty web page repl. (Or — spoiler alert — here's a repl with the complete code from this tutorial.)

When you load the page and click on the “start call” button, a new iframe will be added to the page and you'll see a “The meeting you're trying to join does not exist” message (since we used a placeholder call url in our code).

2. An HTTP endpoint that makes new links

The Daily.co API call to create a new room is very simple. You can test it out yourself, from the command line.

# create a publicly accessible room, with a random name,
# that expires 60 seconds from now
#
curl -H "Content-Type: application/json" \
     -H "Authorization: Bearer $YOUR_API_TOKEN" \
     -XPOST -d \
     '{"properties":{"exp":'`expr $(date +%s) + 60`'}}' \
     https://api.daily.co/v1/rooms/

But if you're making a publicly accessible prototype, then you need to run this API call from somewhere in the cloud. (You shouldn't make the /rooms API call directly from a client web browser, because you don't want to expose your Daily.co API key.)

repli.it to the rescue! Here's a repl that is just what we need — it's a hosted cloud function that listens for HTTP GET requests, calls the Daily.co /rooms endpoint to create a new room, and returns the room info.

The repl uses a Daily.co demo API key, and makes rooms that are valid for 60 seconds. You probably want to clone it, make an .env file with your own Daily.co API key in it, and change the room properties a little bit. (If you don't have a Daily.co API key, yet, just sign up for an account here and then go to the Developers tab to create your key.)

Once you've cloned the repl and put your own Daily.co API key into an .env file, you've got a fully working, publicly accessible cloud function that creates new video call URLs for you on demand!

Note that if you're using a free Daily.co account, you probably want to use short exp times for the rooms. A free API account is limited to having 5 rooms “live” at once and an expired room doesn't count against your 5 room total.

Now we just need to modify our button code to create a new room each time the button is pressed.

// you can replace this with your own repl.it endpoint URL!
const createRoomEndpoint = 'https://create-a-room--kwindla.repl.co';
async function startCall() {
  let response = await fetch(createRoomEndpoint),
      roomData = await response.json(),
      callUrl = roomData.url,
      callFrame = window.DailyIframe.createFrame({
          url: callUrl
      });
      callFrame.join();
}

The fetch call above doesn't do any error handling. For a prototype, that's fine. But for production code, you'd want to handle network errors, retry if possible, and display an error message if you really can't reach the endpoint or you get back data that doesn't make sense.

3. Inviting other people to join this call

Finally, we need a way for other people to join our video call. Let's get a little bit fancy and change our page's URL so that, when you're in a call, you can just copy the page URL and send it to someone else.

First, we'll add a function that we call when our document.body onload event fires. If the page url ends in a hash fragment, we'll assume the hash fragment is a video call link we should immediately join.

<body onload="maybeJoinCall()">

function maybeJoinCall() {
    if (window.location.hash) {
      startCall(window.location.hash.substring(1));
   }
}

Let's modify our startCall() function so that it does what the above code implies — joins a meeting if it's passed an argument, or creates a new video call if it's called without any arguments.

const createRoomEndpoint = 'https://create-a-room--kwindla.repl.co';
let callFrame, callUrl;‍
  async function startCall() {
    if (!callUrl) {
      try {
        let response = await fetch(createRoomEndpoint),
          roomData = await response.json();
        callUrl = roomData.url;
      } catch (e) {
        console.log('fetch failed (retrying in 2s)', e);
        setTimeout(() => startCall(), 2000);
      }
    }
    if (!callFrame) {
      callFrame = window.DailyIframe.createFrame({
        url: callUrl
      });
    }
    callFrame.join();
    window.location = '#' + callUrl;
}

Notice that last line. We're appending our call url to the page's url as a hash fragment.

For a prototype, this “copy the url to share/invite” implementation works great. But of course for a real application, you'd want to do something that makes sense for your app's workflow.

Bonus: leaving the call

If you've tried out what we've done so far, you might have noticed that the “start call” button is visible even while you're in a call. Let's make the button turn into a “leave call” button.

Here's a few more lines to add to the end of our startCall() function

let button = document.getElementById('start-call-button');
button.innerHTML = 'end call';
button.onclick = () => {
  callFrame.leave();
      button.innerHTML = 'start call';
      button.onclick = startCall;
      // window.location.origin is this page's url
      // without the hash fragment
      window.location = window.location.origin
}

We hope you had fun following along with this super-quick intro to on-demand, embedded video calls. Next, you might want to check out the Daily.co REST API docs and front-end javascript library docs). And if you have any questions or suggestions, please send mail to help@daily.co, or ping us on Twitter.

Top image from Unsplash, by Joel Filipe, thank you.Creating on-demand video calls is one of the most common uses of the Daily.co API.

Never miss a story

Get the latest direct to your inbox.