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

A video chat API tutorial on creating no download, in-browser video calls

Creating on-demand video calls is one of the most common uses of the [Daily.co API](http://daily.co/api).

[Here's a demo](https://daily.co/api/demo) showing one-click video calls integrated into the UI of a hypothetical collaborative design tool.

<a href="https://daily.co/api/demo" target="_blank">
![Daily.co API demo example](https://assets.website-files.com/59c9811db5fc1c0001445dbd/5c898a6954de73a7605d1ebf_image-blogpost-apilaunch-democall%402x.png "Daily.co API demo example")
</a>

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](https://repl.it/@kwindla/create-a-room), 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](http://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. Let's make a button that creates an iframe and adds it to our web page.

   -- CODE language-markup --
   <button onclick="startCall()">
     start call
   </button>
   
   <script>
     async function startCall() {
       let callUrl = 'https://api-demo.daily.co/this-is-a-placeholder',
           iframeEl = document.createElement('iframe');
       iframeEl.width = 350;
       iframeEl.height = 425;
       iframeEl.style.position = 'absolute';
       iframeEl.style.right = '1em';
       iframeEl.style.bottom = '3em';
       iframeEl.src = callUrl;
       iframeEl.allow="camera; microphone; autoplay";
       document.body.appendChild(iframeEl);
     }
   </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](https://repl.it/@kwindla/www-empty). (Or — spoiler alert — here's [a repl with the complete code](https://repl.it/@kwindla/zero-to-embedded-video-calls-in-five-minutes) 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](https://docs.daily.co/reference#create-room) is very simple. You can test it out yourself, from the command line.

   -- CODE language-bash --
   # 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](https://repl.it/@kwindla/create-a-room) — 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](https://dashboard.daily.co/?lstate=developers) and then go to the [Developers tab](https://dashboard.daily.co/?lstate=developers) 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.

   -- CODE language-js --
   // 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;
   
     let iframeEl = document.createElement('iframe');
     iframeEl.width = 350;
     iframeEl.height = 425;
     iframeEl.style.position = 'absolute';
     iframeEl.style.right = '1em';
     iframeEl.style.bottom = '3em';
     iframeEl.src = callUrl;
     iframeEl.allow="camera; microphone; autoplay";
     document.body.appendChild(iframeEl);
   }

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.

   -- CODE language-js --
   &lt;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.

   -- CODE language-js --
   const createRoomEndpoint = 'https://create-a-room--kwindla.repl.co';
   async function startCall(callUrl) {
    if (!callUrl) {
     let response = await fetch(createRoomEndpoint),
       roomData = await response.json();
       callUrl = roomData.url;
     }
   
     let iframeEl = document.createElement('iframe');
     iframeEl.width = 350;
     iframeEl.height = 425;
     iframeEl.style.position = 'absolute';
     iframeEl.style.right = '1em';
     iframeEl.style.bottom = '3em';
     iframeEl.src = callUrl;
     iframeEl.allow="camera; microphone; autoplay";
     document.body.appendChild(iframeEl);
     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

   -- CODE language-js --
   let button = document.getElementById('start-call-button');
   button.innerHTML = 'end call';
   button.onclick = () => {
    document.body.removeChild(iframeEl);
     iframeEl.src = null;
     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 API docs](https://docs.daily.co/reference). And if you have any questions or suggestions, please send mail to help@daily.co, or [ping us on Twitter](https://twitter.com/trydaily).

*Top image from Unsplash, by Joel Filipe, thank you.*

Recent posts