Real-time Collaborative Drawing with GraphQL & AWS AppSync

dabit3 profile image Nader Dabit Updated on ・3 min read

To see the code for this & to launch this project, click here to go to the GitHub repo.

I am putting together a couple of demos for my upcoming talks at React Day Norway & React India.

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

  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:

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:

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:

npx create-react-app canvas-app

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

amplify init

amplify add api

# When prompted, I use the schema I referenced above

amplify push

Finally, I created 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 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.

My Name is Nader Dabit. I am a Developer Advocate at Amazon Web Services working with projects like AWS AppSync and AWS Amplify. I specialize in cross-platform & cloud-enabled application development.


Editor guide
olivercole profile image
Oliver Cole

I love the idea, and the platform, and I watched one of your AWS webinars - I’d love to build something with this stuff.

But I think you should disclose your affiliation at the top of the article, rather than the bottom.

_jfcorsini profile image
João Fernando Corsin

Great post, Nader. Thanks!