How I Built HypeBeats - A Real-time Collaborative Beatbox with React & GraphQL
Tags: react, graphql, awsappsync
Published: 2019-03-19 15:17:46

---
title: How I Built HypeBeats - A Real-time Collaborative Beatbox with React & GraphQL
published: true
description: How I used GraphQL Subscriptions to build a real-time collaborative beatbox with React Hooks Drum Machine & AWS AppSync.
tags: react, graphql, aws appsync
---

{% youtube nm2kt3h1--c %}

>To view the live demo, click [here](https://www.hypebeats.dev/#/).
>To view the repo, click [here](https://github.com/dabit3/hype-beats).

---

I’ve been playing around with GraphQL subscriptions quite a lot lately, adding real-time functionality to applications to make them interactive. Last week, I released a real-time drawing app using [react-canvas-draw](https://embiem.github.io/react-canvas-draw/):

{% twitter 1105089664040554496 %}

A few weeks ago I saw this talk at React NYC about building a beatbox using React Hooks.

{% youtube 7FRHuVNVCj4 %}

I was pretty hyped after watching it. I then found the repo for it, cloned it & started thinking what I could do to make it even more interesting.

{% github kenwheeler/hooks-drum-machine %}

The drum machine basically has an assortment of beats (bass, clap, snare, etc..) that run through a step sequencer:

![](https://thepracticaldev.s3.amazonaws.com/i/4r1v7qjtmvsrtj2iz88t.png)

With a step sequencer you move in sequence from left to right stepping over each item in the sequence. If the item is highlighted, the associated sound plays.

![](https://thepracticaldev.s3.amazonaws.com/i/32w5xy90uv0fja6gzl9a.gif)

The drum machine gives us an initial state of beats with an array set for each beat in the sequencer:

![](https://thepracticaldev.s3.amazonaws.com/i/0wxsqf2i8abpy79es9y9.png)


If a beat is set to 0 it does not play (not highlighted), if it's set to 1 (highlighted) then it does play, if it's set to 2 (blinking) it plays triple.

> To learn more about how the drum machine works under the hood, check out the video [here](https://www.youtube.com/watch?v=7FRHuVNVCj4).

## Making it collaborative & real-time with GraphQL subscriptions

The idea I had was making this collaborative. To do so, I needed to add the capabilities to create & share unique drum machines. Users can make updates / changes to the machines in real time & the music will update across all machines as changes are made.

To do this, I needed to do three main things:

1. Make the drum machine dynamic
2. Add routing
3. Add real-time functionality, ideally GraphQL subscriptions

To make the drum machine dynamic & add subscriptions,  I created a basic GraphQL schema to hold the drum machines that I deployed using AWS AppSync:

```graphql
type Beatbox @model {
  id: ID!
  clientId: ID!
  beats: String!
  name: String!
}
```

Because the state of the drum machine is a basic JSON object, I figured we could `stringify` the data & store it in our database pretty easily.

The other thing I had to think about was routing. To do so, I used [React Router](https://github.com/ReactTraining/react-router) & came up with a routing scheme that looks like this:

```js
/machine/:id/:name
```

In addition to the beat data, each drum machine has a unique `id` & a `name` property for us to use to identify  it & query for it.

There is also a `clientId` in order to handle subscription data, giving us a way to filter out duplicates on the client.

When the user lands on the route, for example:

```js
/machine/d562581d-2a2d-4597-a6bb-2580deaf0254/BassLord
```

We parse the url & retrieve the machine name & id.

We use the machine name in our UI & we use the id to create or query for the machine.

When the user makes changes, we trigger an update in our API:

```js
// DrumMachine.js
async function updateBeatbox(beats, machineId) {
  const beatbox = {
    id: machineId, clientId, beats: JSON.stringify(beats)
  }
  try {
    await API.graphql(graphqlOperation(UpdateBeatbox, { input: beatbox }))
    console.log('successfully updated beatbox...')
  } catch (err) {
    console.log('error updating beatbox...:', err)
  }
  return () => {}
}
```

The `updateBeatBox` method is called in [Step.js](https://github.com/dabit3/hype-beats/blob/withroutes/src/Step.js).

We also create a subscription to listen for updates in the GraphQL API:

```js
// DrumMachine.js
useEffect(() => {
  const subscriber = API.graphql(graphqlOperation(onUpdateBeatbox)).subscribe({
    next: data => {
      const { value: { data: { onUpdateBeatbox: { clientId: ClientId, beats }}}} = data
      if (ClientId === clientId) return
      setSteps(JSON.parse(beats))
    }
  });
  return () => subscriber.unsubscribe()
}, []);
```

Other than that, I pretty much used the functionality of the drum machine as is!

>To view the live demo, click [here](https://www.hypebeats.dev/#/).
>To view the repo, click [here](https://github.com/dabit3/hype-beats).

## Contributing / Next Steps
The next things I'd like to do to this is add more beats! I'd also like to add some more sounds. If you'd like to contribute to this, feel free to [reach out to me](https://twitter.com/dabit3) & or [submit a pull request](https://github.com/dabit3/hype-beats/pulls)!
If you'd like to deploy this application yourself, check out the documentation in the repo to get up & running.

---

> My Name is [Nader Dabit](https://twitter.com/dabit3). I am a Developer Advocate at Amazon Web Services working with projects like [AWS AppSync](https://aws.amazon.com/appsync/) and [AWS Amplify](https://aws-amplify.github.io/). I specialize in cross-platform & cloud-enabled application development.