Go back to 8base Academy
July 11, 2020

Building a Public Chat Room with GraphQL Subscriptions

Sebastian Scholl

This is an automated transcription. Pleas excuse inaccuracies.

Hi, my name is Sebastian. I'm the product manager here at 8base. If you find this video helpful please like it as well as subscribe to our channel- it really helps us grow. So, in this video we're going to be building a public chat room using GraphicQL subscriptions and VueJS for our front-end framework. This is going to give you a great primer on how to use subscriptions to build real time notification applications, a real-time event application for example, messaging apps, notification feeds or anything else that you want to use essentially behind the scenes web sockets for. So, let's just dive right in and go ahead and build this.  


So, what I did the other day was went ahead and made a tutorial for how to build this chatroom. Frankly, it will take anywhere from like 10 to 15 minutes it's really fast. What we're going to do is we're going to use VueJS for the front-end with Apollo client as our Graph QL client and then 8base for the backend. 8base will give us all the resources we need to set up our back-end and use the subscriptions via GraphQL. So, what we're going to do is we're just going to walk through this tutorial step by step I'll complete it with you, however I'll add some context to all the steps as we go through them. Well, alright let's get started.  


So, the first thing that we're going to do is go ahead and set up our project so for example, here it is we're in the git repo right now. So, what I'm going to do is I'm going to go ahead and go to the root of this repo get the get URL and we're going to go ahead and clone it down. Open the terminal and I'm going to move into my code directory that's where I like to work out of and run “get clone” add in that and I'm just going to call it group at. Awesome. Let that run, yep it cloned it down. Cool, so now I'm going to move into the group chat directory and next it's going to stay up just run yarn. We're going to run yarn install all the dependencies that we need.  


So, the next thing that we're going to do is we're going to actually add a dot ENV dot local file to our project. This is going to allow us to specify any environment variables that we need for our group chat component to actually work; namely the endpoints and then the 8based workspace ID that we’ll be connecting to. So, there's this little command that we can just run in our command line here. Essentially, we're just echoing this into a new file called dot ENV dot local. Awesome! So, now if I open up my files right here [I'm going to make this full screen] I can go ahead and [oh we actually have to open the folder here]. So, I'm going to go ahead open the folder, code, group, chat, done and here our ENV dot local. And so, it's asking for our 8base workspace ID, however we're going to go get that in just a minute.  


Back here now what we can do is we can go down and now look okay, so now it's going to tell us to import the schema. So, we could easily go ahead and build out our data model and 8base it's a very simple data model as you're going to see. However, this is a great way to just get introduced to the 8base command line tool and it will just scaffold the data model that we're going to need for this project.  


So, I'm going to go ahead and just reinstall the command line. So, 8based global, add 8base CLI that will just take a second. And then while that's downloading, we're going to then have to actually authenticate our command line. So, that's going to add an 8base RC file to the root of your computer that will store some authentication credentials. So, 8base login and to do this is actually going to launch the browser and then it's going to four log ins to 8base, it is authenticated. And we are good. Well just going to close that now. All right so now with that authenticated now what we're going to do is, actually import our schema. So, we can see that the 8base command line gives us this import statement and then we can pass it a file path as well as the workspace ID. However, first what we're going to actually want to do is go get that workspace ID so I'm going to go ahead and do that. I'm going to open a new tab app.8base.com. Once here, I'm going to log in be back in one second okay cool.  


So, I was able to log in eighth base and essentially, I just have a basic workspace for this demonstration here. You can use any workspace that you have even a current project and just add the table if you wanted to do it that way. But what I'm going to do is I'm going to go down into my settings I'm going to get my workspace ID- that's going to be important here. So, first off let's go back to VS code and what we're actually going to start by doing is by configuring the project. So, what that means is we're going to run 8base configure and pretty much tell 8base what works based this this repo is going to be dealing with. So, first off let's go down to group chat that was the name of my workspace we're done there and next we're going to use that import command that we saw in tutorial. So, let's go to 8base import - F. We're going to give it the file path which is chat schema, it's right there. Then we're going to say that the workspace ID is the one we just copied. From that cool- so this should be going alright, it's importing the schema. This is essentially just going up in a scaffolding the data model that we need for the chat room.  


The second thing we're going to do here too is we're going to just in this dot ENV dot local file, we are going to add our workspace ID or set that variable well paste that in there. Awesome!  


Now if you just want to look at these environment variables really quickly, we can see that we have two API endpoints; one for just our Graph QL requests and the other for our WebSocket requests. So, to the API endpoint we're going to be making our queries and Mutations. To the WS endpoint we're going to be making our subscriptions or WebSocket unit. And then the workspace ID we're going to use in both those different API modules that we're going to create to specify essentially which workspace at those endpoints we are going to be dealing with.  


So, let's jump back over to our tutorial. Okay so we imported the schema now we want to go set the API permissions. So, essentially, we're going to make this a public chat room, but we're not going to handle authentication. And what we're going to want to do is essentially tell the workspace what permissions we want a guest do you have. The guest role is a special role in 8base. It means public permissions, so you don't have to pass any off headers, you don't have to identify who you are, anyone that wants to hit the API can then perform these actions. So, let's go back to our workspace, let's go to our app services roles click on “guest”. And here we look back here we can see that okay, what we're going to want to do is make sure that the users we can do all the user's operations and then the messages operation pool. So, if I go back in here, I'm going to say users I'm going to say, “All records” and cool. Then we can see that we have the messages table here let's go back and look at reload this page is it should have imported our… cool. So, we have our messages. This table was imported with the import that we ran. But now if we go back to our roles on guest, we can see… cool, now we can do it with messages. We want to be able to create messages and we want to be able to be all messages. I think that's going to settle it if not we can come back later and update it as needed.  


Right now, then we are now moving on to actually writing our queries. So, these are going to be all the queries we need to run a chatroom. We're going to read through them really quickly and then copy them into our project as it's apps where they're going to need to work. So, for the first one we're going to see that okay well we have a few different Graph QL queries writing here. The first one is an initial chart data. Essentially when we load this chatroom we're going to say give us all the users and then give us the last ten messages, so we can populate it with some activity. Then we want to be able to create a user which makes sense because whenever a user is created- we want to be able to create a user whenever they join the chatroom. We want to delete a user whenever they leave the chatroom; once again it's like public chat room so we just want to get rid of people after they leave. Then we want a user subscription. So, you look at the subscription you can see that we say hey we want a subscription on the users table whenever there's a Mutation that's create or delete. And when that happens, we want the Mutation name back as well as the node [which would be the user in this case] with their ID and email. So. this is going to allow us to do those real-time listens to those real-time events. And pretty much the same thing runs for messages we want to be able to create messages. Connect them to the author that's the person that's the chatroom participant, as well as listen to messages being created on the create event and get back some of the data from that message that we created.  


So, let's copy this over to our project. We can see that it's telling us to put it in the utils Graph QL.JS file. Utils Graph QL.JS we're going to pop that right in there and keep cruising.  


So, next up we're actually be creating our API clients that's both the Apollo client and then a description client for our WebSocket or our subscriptions. So, we can see I'm actually going to copy this over to our code editor so we can enjoy the syntax highlighting. We can see that this one's supposed to go in source utils api.JS; so api.JS right here- awesome. Drop that in. Essentially, we can see that we're importing Apollo client from Apollo blue boost HTTP, HTTP link in memory cache. We're getting our environment variables from our environment file. And then we are initializing the Apollo client with pretty much the basic options that you can give it. And what we're going to do is we're in as well or interpolating the endpoint with the workspace ID, So, it's going to be a API.8base.com/your workspace ID- that is the endpoint you'll have to use to run the basic Graph QL queries against the API queries in Mutations. So, with that done we initialize that we export it and we can use it in our view component.  


Now if we go back, we can see that the next one is the subscription client. Once again, I'm going to copy this over and then we can talk about it because once again this one is a little bit more involved than the last one. So, let me copy that cool and this one's supposed to go in utils.WSS- boom right there. Alright copy this over. And so essentially what we're doing is we're going to be importing the implementation of WebSocket that we want to use in our subscription client as well as the subscription client itself which we're going to use from subscriptions transport WS. Make sure it's an Apollo managed package and then we're going to be importing once again the endpoint and the workspace ID.  


Now when we go ahead and we initialize our subscription client. We're going to be given at the endpoint we're going to specify the reconnect true parameter; so, if it disconnects for some reason it'll automatically reconnect. And then pass in the connection program workspace ID and set that to our workspace ID. Now this is different, then we did it with the API client in which we are part of the URL path. Here were actually putting it as a connection pam which kind of comes out as a header- think of it that way. And then lastly, we're going to be specifying in the subscription client what implementation of WebSocket we want to use which is the isomorphic WS that we imported; so, adding that right there.  


Once that clash is initialized while we're going to do is, we're going to export an object with two methods on it bribe and close. This subscribed method is the one that we're going to be passing our query or subscription queries to with the options that we want to use; those options being, “Hey, what's the data callback that we use when the subscription client receives an event or the error when there's an error callback and of course any variables that we're actually passing to our subscription.” And so, we create that, we get the result back and then whenever there are these events which is next or error on the subscription client, we are passing the result to those callbacks that we defined ourselves- so, pretty straightforward. And in the close method the subscription client has a close method on it we're essentially aliasing, so we can use easily. Once that whole thing is configured, we just export it and once again we can use it now in our component- pretty straightforward.  


So, now what we're going to do is actually go in and write out our view component. And what's pretty cool is this whole chatroom is just going to be one view component and it's going to be pretty straightforward. But you can use this in any project you want; you can even use it in an on-view project if you just wanted to add view as part of project as view is that that lightweight. But let's hop back and first off, we're going to need our imports- so pretty straightforward. Bring these over, I'm going to add them to the OP of our script file and what we can see here is we're importing the API and the WSS modules that we just looked at initializing. We're importing all the different Graph QL queries, subscriptions, patients that we had written in the Graph QL.JS file and then we're importing some styles.  


Now I promise you these Styles are not pretty to look at. You can develop any type of client application or any looking field that you want and I encourage you to do that. I wanted this to be as bare-bones possible so that you can and should look at the concepts, but we'd not get distracted with any type of SS writing or whatnot; so, drop those in there.  


Now if we go down, we can now see that the next thing we want to add is our component data, so I'm going to bring this over and we'll talk through each one that we are adding in. So, first off is in this data function we're returning an object which is going to have messages array on it, so that's we're going to store all our message objects. We're going to have a new message which is where we're going to potentially put the string this the draft being a message before they sent it. Then we have this object called, “Me” which by default has an empty email that's going to represent the user that is participating in the chatroom and then users which is going to be everyone in the chatroom- we're going to keep track of that and manage that array.  


So, let's just save that and then we're going to go back and now what we're going to be adding is our lifecycle hooks. So, depending on what framework were you use and just to reiterate that you can do this with any framework that you'd want to use. The components might have different life cycles or you might trigger it at different ways and with view we're using the lifecycle hooks create and before destroy which run when a component is first created and then when it right before it's destroyed. Essentially what we're going to want to do in these lifecycle hooks is initialize the chatroom with the data we need, initialize the subscriptions that we want to listen to for when users are created, deleted or messages are created. So, we can just see that right here pretty clearly, so when it's created this created function is going to run, we're going to use that WSS model and subscribe through the user subscription which we wrote back here I'm at look at. So, a subscription on the user's table, let's only get something when there was a Mutation on create or delete and let's get the Mutation back and the node with the information. So, that is pretty straightforward we're going to pass that subscription and then the data callback is going to be handle user function which we've yet to write, but we're going to look at that in just a second. Same thing with messages, WSS, subscribe to the message's subscription, give it the callback data, add message.  


Then we're going to run an API query with and get the initial chart data and from the response that we get, we're going to get the data back and then assign the users list items to the users in our component data and then the messages list items to our messages on our component data. And then one thing I added here too was that, before if you were to reload the page this call back would be triggered that's just going to run this close chat method which we're going to look at in a second to essentially delete the user that was in the chat and cancel their subscriptions. And then that same thing is going to run them before, destroy, cool.  


So, now what we're going to do is we're going to go past that and now the component methods. So, there's a few more of these but we're going to breeze through them really quickly because they're pretty self-explanatory and you'll be able to jump in and play with them yourself if you'd like to. I'm just going to copy over the user or the methods object here with all the methods on it. So, let's just drop that in there, cool that there. I don't know where that comma came from and awesome let's just run through this now.  


Okay, so now we have the methods and these are the methods that are available on our component we have a create users method what does it do, it hits the API, runs a Mutation with the create Mutation and gives it the email address as a variable pretty straightforward. We have a delete user method it hits the API with a Mutation delete user, passes it the ID- nice. We have a handle user callback. So, once again in the created lifecycle hook, we're using this handle user for the user's subscription.  

Now when that subscription returns data or that event is triggered it's going to tell us the Mutation that ran create or delete. We have this you know this little switch statement right here essentially that's well hit the correct all back from this object and then invoke it passing the note is data which is add user and remove user which is right here. So, if it's add-user, we get the user if the email address is the current participant email address, we set that user to the me record on the me data property on the component. And then we also just will always push it into the user's array. Remove user- we filter the user by its ID out and that can be any user whether it’s current participant or any other participant. Because remember one cool thing to notice here is that even in like the delete Mutation that we run or create Mutation that we run, we're actually not listening for any response because we're getting those responses through our subscriptions. So, we're just sending these off and expecting them to come through subscriptions which is just a really nice clean way of handling it.  

Then we have our create message method a straightforward, create message, give it the ID in the content and then when after this is run, we're actually listening to the response here. We're just going to clear the new message. Essentially that message was created, we emptied it, but add message, get the message back from the subscription, put it into the messages array and then close chat; which is we're going to close from the close method on our subscription client. Now that will actually close our subscriptions for both our users subscription as well as our messenger subscription- this is the same client just two different queries, as well as we're going to run the delete user method which we just looked at and set me back to the empty default- pretty straightforward.  


So, going back here now let's roll down and look at component template. Now you can build it once again a template, however you want to you can do it with any framework you want to. This is essentially like what are is the basic template that you need to make this messaging app functional. However, we will just go over really quickly. So, first off if me that's the current user has an ID that means they are created user, then we'll show the chat. If not, we're going to go down to the if-else statement we have a chat signup symbol form. Signup and there's an input where it uses the email address. So, it's bound to the email address, so as you type in, it's going to say that is your email address and when you blur the input it's going to go ahead and create the user using that email address that you put- that's it and so once that subscription returns that user if it was you then the email addresses are matching, it sets you and your ID, sends you those ID, drops into the chat component. It tells us how many users are online. We then have a closed chat button we can use. I want to close out the chat. For every message that we have we're going to render it out and we're going to add this me class essentially to where if the user ID or the participant ID is your ID, then I think this is actually author. I'm going to update that and hope for the best.  


Actually, what we can just do we can look back at our Graph QL script descriptions and we can see that we get a message author_ID_email- cool. I have that right. So, if the message author ID is equal to your ID, then we're going to be using me class and that's how we'll delineate, “Hey, should these messages or yours go on which side of the screen?” So, you can see where your messages are. And then very simply there's an input for a new message that once you write it you click create message and it's going to send that.  


So, pretty sure that's it. Let's boot this thing up and see what happens. So, Yarn serve, run that. This will probably just take a second to boot up and since what we're going to do is first, we're going to see if it works and then we're going to open two windows and watch kind of a chat work back and forth with each other. So, let's go here, reload this okay what's my email address? It's John@Yo.Co. Right, exit out the input and cool. So, it says, there's two users are online. We go into our 8based workspace. Then we go to our users table, we can see here that John@Yo.Co signed up and then my default account is there. So, I'm going to write my first message which is going to be hello. And that hello, I'm on the right side of the screen there. Now there's no one else to talk to, so I'm going to open another browser tab, localhost 8080. Here I'm going to say I'm Steve@Me.Co. And Eve is now in the chat room. So, three users online and if I go back to this window three users online- all right, all this is working through and this one's on the right side of the screen. So, “Hello what's up John.” Cool and I go back here and got the message, right. So, here's our subscriptions. The chatroom is all alive. So, we can just say something random like, hello again and send that- awesome! And so here we go and then once again what's even cooler we can just keep adding this. So, if this was a chat room everyone could just keep piling on. Let's say Jess at Yo.Co and Jess is now in the chat room. “Hey, guys”- sure you guys are thrilled at this point of me talking to myself like three different personalities but as you can see this is all working pretty seamlessly.  


So, I hope this video gave you a good idea of how easy it is to get started using subscriptions and building real time event-driven components or applications. This is just the surface right- there's so many other things. You can do we could do different channels, we could do authenticated private messages images, all these different things and build a really rich messaging application. And if this video is well received, if you guys like it ask for it in the comments, vote it up- absolutely will that be the next thing that we dive into. Once again, if you found this video helpful please like it as well as subscribe to the channel. Thanks for watching and looking forward to seeing you in future videos.

Share this post on social media!

Ready to try 8base?

We're excited about helping you achieve amazing results.