Spook your colleagues with a Halloween themed virtual standup 👻🎃✨
Tags: javascript, video, webdev, halloween
Published: 2020-10-27 00:01:04

Holidays like Halloween are shaping up to look a bit different this year, with most office celebrations going virtual. But have no fear, spooky season always finds a way! 

At [Daily](https://www.daily.co/), we power 1-click video for websites and apps. Developers use our tools to embed fully functional prebuilt video chat widgets in minutes, and to build [completely custom call experiences](https://dev.to/trydaily/build-a-video-chat-app-in-minutes-with-react-and-daily-js-481c). In this tutorial, we’ll use Daily’s [prebuilt UI](https://www.daily.co/blog/prebuilt-ui/) to play trick-or-treat in our next virtual standup. 

![Colleagues on video chat call with candy in the background](https://dev-to-uploads.s3.amazonaws.com/i/8fdxgg13mkiz9womutk6.png)

##What we’ll build 
We’re going to embed Daily’s video chat widget into a webpage. We’ll decorate the page using a little CSS, JavaScript, and a whole lot of gifs. We’ll also listen for [Daily API events](https://docs.daily.co/reference#events) to set random background images and sound effects when participants join the call. 

##What you’ll need to build it 
* [Daily account](https://dashboard.daily.co/): Sign up if you don’t have one already! 
* [GIPHY API key](https://developers.giphy.com/): So that we can have some fun with gifs. 

![Hocus Pocus witches say just like this](https://media.giphy.com/media/137e3cY5NMH20M/giphy.gif)

##How to build it 
###Create a Daily room and embed the room on your webpage 
A Daily room URL is made up of your unique Daily domain followed by the room name. Each room URL points to a unique video chat location, and looks something like:

`https://your-domain.daily.co/<room-name>/`

You can create rooms either through a POST request to the [/rooms Daily API endpoint](https://docs.daily.co/reference#create-room), or from the [Daily dashboard](https://dashboard.daily.co/). Pick whichever method and name you’d like. I went for the dashboard and set the room name to `spooky`, of course. 

![Daily Dashboard screenshot of Create Room page](https://dev-to-uploads.s3.amazonaws.com/i/ze7fi0yqoha5war0ic46.png)

Once you have a room, you can use Daily’s prebuilt UI by embedding the room URL into any website or app, for example:

```html 
<html>
  <script src="https://unpkg.com/@daily-co/daily-js"></script>
  <body>
    <script>
      callFrame = window.DailyIframe.createFrame();
      callFrame.join({ url: 'https://your-team.daily.co/<room-name>' })
    </script>
  </body>
</html>
```
In our demo, we also take advantage of the DailyIframe [`iframeStyle` property](https://docs.daily.co/reference#properties) to position our video chat before we call the [`.join` method](https://docs.daily.co/reference#introduction): 

```js
callFrame = window.DailyIframe.createFrame({
         iframeStyle: {
           border: 0,
           display: 'block',
           margin: 'auto',
           width: '50%',
           height: '100%',
         },
       });
```
_**Note**: While we’re hard-coding our room URLs for the purpose of this demo, in production code you’ll want to generate your meeting rooms dynamically server side, without revealing them on the frontend. Read about how to set up [an instant server with Glitch](https://dev.to/trydaily/deploy-a-daily-node-js-backend-server-instantly-9f4)._ 

###Randomize the background image
I definitely spent more time deciding what images to use for the backdrop of the call than I spent integrating the Daily video chat widget. I went down a little bit of a rabbit hole, and ultimately wound up using images from [Unsplash](https://unsplash.com/images/events/halloween), [pixabay](https://pixabay.com/images/search/haunted%20house/?pagi=2), and [Pexels](https://www.pexels.com/search/halloween%20house/). I also really appreciated the Halloween illustrations on [Mixkit](https://mixkit.co/) and [Undraw](https://undraw.co/search). Choose whatever speaks to you, the world is your cauldron! 

![Witches stir a cauldron](https://media.giphy.com/media/tNWSLtkQh0Oli/giphy.gif) 

Once you’ve picked your images, it’s time to turn to [Daily events](https://docs.daily.co/reference#events), and listen for whenever a __local__ participant joins a call. Whenever the `joined-meeting` event fires, we’ll call a function to set the background image: 

```js
callFrame
         ...
         .on('joined-meeting', setBackground)
         ...
```

Our `setBackground` function stores a list of our photos’ names in an array. It then uses the length of the array and the built-in [JavaScript Math object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math) to pick a random array index. Once the random index is selected, the function manipulates the [DOM body property](https://www.w3schools.com/jsref/prop_doc_body.asp) to set the page's background image.

```js
async function setBackground(event) {
       try {
         const photos = ['candy.jpg', 'forest.jpg', 'jack-o-lanterns.jpg'];
         let randomIndex = Math.ceil(Math.random() * (photos.length - 1));
         document.body.style.backgroundImage = `url('/static-demos/spooky-demo/assets/${photos[randomIndex]}')`;
       } catch (error) {
         console.error(error);
       }
     }
```

In `spooky.css`, we set the body’s `background-size` property to `cover`, so the image, like the spooky forest below, will cover the entire screen behind the call. 

![Screenshot video call ontop of forest background](https://dev-to-uploads.s3.amazonaws.com/i/06y0a2iat88bz8sqgmem.png)

###Rotate gifs 
If random festive backgrounds are the trick, then rotating random gifs are the treat. To add these to your call, first you’ll need your [GIPHY API key](https://developers.giphy.com/). 

Our `getGifs` function makes a request to the [GIPHY API search endpoint](https://developers.giphy.com/docs/api/endpoint/#search), and passes in a search query for Halloween gifs that are rated pg. It saves the response, an object full of gifs, in the `gifs` variable, which it returns.  

```js
async function getGifs() {
        try {
          // TODO: replace the below with you giphy API key
          // In production, you'll need to store your key securely, vs. hard coding
          const token = 'YOUR-GIPHY-API-KEY';
          const giphyEndpoint = `https://api.giphy.com/v1/gifs/search?api_key=${token}&q=halloween&rating=pg`;
          const response = await fetch(giphyEndpoint);
          const gifs = await response.json();
          return gifs;
        } catch (error) {
          console.error(error);
        }
      }
```

We’ll call `getGifs()` within our `run` function. We call `run()` as soon as the page loads. Within `run()`, [every 20 seconds](https://www.w3schools.com/jsref/met_win_setinterval.asp) we extract a random gif's url from the gifs response object. We save the randomly selected url in a `url` variable. We can now set the `src` property of `<img id='gifs'>` to `url`.

```js
const gifSearchResults = await getGifs();

        setInterval(() => {
          try {
            let url =
              gifSearchResults.data[Math.floor(Math.random() * 50)].images
                .original.url;
            document.getElementById('gifs').src = url;
          } catch (error) {
            console.error(error);
          }
        }, 20 * 1000);
```

If you’re curious about how we styled our gifs, here’s how we made them rotate through a circular "moon" in the top-right corner: 

```css
#gifs {
   object-fit: contain;
 }
 
 #gif-wrapper {
   position: fixed;
   border-radius: 50%;
   border: 2px solid #e2dccd;
   background: black;
   width: 15vw;
   height: 25vh;
   top: 2%;
   right: 5%;
   display: flex;
   justify-content: space-evenly;
   align-items: center;
   overflow: hidden;
 }
```

But you should feel free to style however you like! Much like costumes, no one CSS style suits everyone. Make it your own! 

###Add sound effects to Daily events 
Much like picking a background image, landing on my sound effect of choice was tough. I wound up going with a clip of The [Addams Family theme song](https://www.myinstants.com/instant/the-addams-family-intro-theme/), but there are lots of options out there for creaky doors, cackling witches, and anything else you can imagine. I just couldn’t say no to these faces. 

![Addams family snapping](https://media.giphy.com/media/15bj76PJIEXr7pUWNi/giphy.gif) 

Once you have your sound, save it in your project. I put mine in my `/assets` folder along with my background images. Then, add an `<audio>` tag to your HTML:

```html
<audio src='assets/the-addams-family-intro-theme-song.mp3'></audio>  
```

Just like we did whenever the **local** participant joins a call, we added an event listener to play a sound whenever _another_ participant logs on. We listen for the `participant-joined` event. 

```js
callFrame
	  ...
         .on('participant-joined', playSound)
	  ...
```

When that happens, `playSound` finds our `<audio>` element and calls the [DOM `play()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play). 

```js
async function playSound(event) {
       try {
         const sound = document.querySelector('audio');
         sound.play();
       } catch (error) {
         console.error(error);
       }
     }
```

##What’s next
There’s so much more you can do to customize your call: experiment with different event listeners, styles, etc. You could even build an entirely custom call using [the Daily call object](https://docs.daily.co/docs/build-a-custom-video-chat-interface), e.g. placing participants' video streams in the windows of a haunted house.  

You can customize Daily calls for any spooky or special occasion. I got the idea for this post from all of the fun wedding send-offs and birthday surprises my colleagues have built (especially [Mattie Ruth](https://dev.to/mattieruth)!). If you want to get in on all that fun and more, including the challenges of building video chat infrastructure, [we’re hiring](https://www.daily.co/jobs)! Please [send me a note](https://twitter.com/kimeejohnson) if you’re interested in joining the team. I’m happy to help any way I can. 

![Team dressed up on video call for wedding send-off](https://dev-to-uploads.s3.amazonaws.com/i/65pzruwh5d5dprbw0qk2.png)