Real-time Collaborative Drawing with GraphQL & AWS AppSync
Tags: graphql, javascript, react
Published: 2019-03-11 12:45:37

---
title: Real-time Collaborative Drawing with GraphQL & AWS AppSync
published: true
description: How I built a real-time collaborative drawing tool built on GraphQL subscriptions using AWS AppSync.
tags: graphql, javascript, react
---

![](https://i.imgur.com/6yMuOb6.gif)

> To see the code for this & to launch this project, click [here](https://github.com/dabit3/appsync-graphql-real-time-canvas) to go to the GitHub repo.

I am putting together a couple of demos for my upcoming talks at [React Day Norway](https://reactnorway.com/) & [React India](https://www.reactindia.io/).

For these talks I'm demoing interesting use cases of GraphQL & GraphQL subscriptions. Many of the ideas I have focus on the real-time aspect of GraphQL subscriptions because it enables us to build real-time functionality quite easily.

I stumbled across a library called [react-canvas-draw](https://github.com/embiem/react-canvas-draw) that looked pretty cool. What I liked about it was that not only was it a library that allowed for drawing, but it saves the strokes in an array & then allows you to paint them back in the same sequence in which they were created!

This seemed like a perfect use case for my application. The data structure for the lines stored for painting on the canvas looks something like this:

```js
{
  lines: [
    { points: [{ x: 132, y: 144 }, { x: 133, y: 145 }], "brushColor":"#FF6D00","brushRadius": 4 },
    { points: [{ x: 132, y: 144 }, { x: 133, y: 145 }], "brushColor":"#000","brushRadius": 4 }
  ],
  width: "400px",
  height: "400px"
}
```

The basic thought I had was finding out some way to extract this data & update it in a GraphQL api, then when updated trigger a subscription. React Canvas Draw has a few methods that make this pretty easy. In fact, they expose quite a few methods that allow for full control over painting the canvas. Let's have a look at a couple of them that I used:

- getSaveData - This method gives us the current canvas state
- loadSaveData - This methods allows us to write an entire data set to the canvas
- simulateDrawingLines - This method writes a single line to the canvas

Now that we know how we're going to interact with the canvas, how are we going to interact with the GraphQL API?

To begin with, I created a basic schema:

```graphql
type Canvas {
  id: ID!
  clientId: String!
  data: String!
}
```

The main thing we need to keep up with is the unique `id` of the canvas as well as the canvas data which we store in a field called `data`.

Using AWS AppSync, we can scaffold out the rest of the Schema as well as the data sources & resolvers by adding the `@model` directive when used with the Amplify CLI & [GraphQL Transform library](https://aws-amplify.github.io/docs/cli/graphql#graphql-transform):

```graphql
type Canvas @model {
  id: ID!
  clientId: String!
  data: String!
}
```

## Steps to build this from scratch

So to get this up & running, I created a new React application:

```sh
npx create-react-app canvas-app
```

Next, I initialized a new amplify project & then added the API & schema

```sh
amplify init

amplify add api

# When prompted, I use the schema I referenced above

amplify push
```

Finally, I created [__Canvas.js__](https://github.com/dabit3/appsync-graphql-real-time-canvas/blob/master/src/Canvas.js) to hold all of the main code for my application & used this file as the main file in my application.

I then created a new file called [__RCD.js__](https://github.com/dabit3/appsync-graphql-real-time-canvas/blob/master/src/RCD.js) that holds the `react-canvas-draw` library. I referenced it locally just in case I needed to make updates, but also to have it locally to be able to easily experiment with the different methods available.

That's it! Using GraphQL subscriptions makes it really easy to get up & running with real-time applications. If you have any questions about this, feel free to [ping me any time](https://twitter.com/dabit3).

> 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.