Create a realtime web app with Hasura and Gatsby — Learn With Jason

Articles, Blog

Create a realtime web app with Hasura and Gatsby — Learn With Jason

Create a realtime web app with Hasura and Gatsby — Learn With Jason


– All right! Hello, everybody. It’s Jason, back again, and today we’ve got
Vladimir Novick from Hasura who is gonna teach us how
to build a realtime web app which I’m super excited to try. I’ve looked at Hasura, I’ve always liked realtime stuff. I don’t know. Fun trivia fact, I actually wrote a book about realtime web apps
way back in the day. So this is gonna be a fun
little trip down memory lane for me, digging back into this. Vladimir, do you wanna give
an overview of who you are and what we’re gonna talk about today? – Yeah, yeah, sure. Yeah, first of all, hi everyone. Thanks, Jason, for introducing me. So yeah, I’m developer advocate at Hasura. I’m doing lots of stuff in web/mobile VR, AR, and IoT fields. I usually like to joke that I probably need
to add a IM blockchain to be on top of buzzwords or something. (both laughing) Yeah. And today, we will totally gonna build realtime app with Gatsby and Hasura. Yeah, I think we’ll manage to do something in recreating this. How much time we have an hour and a half, something in that shape?
– Yeah. We got about 90 minutes, yeah. – Yeah, cool. – So cool. Let’s dive right in, I guess. How do I start? I assume I click Get Started? – No, actually, not. Get Started will lead you to docs. But let me give you a brief overview about Hasura in general, right. – Sure!
– So what Hasura basically is, it’s free and open source engine that gives you a realtime
GraphQL API on top of Postgres, which is a nice thing. It’s written here on the
website is on top of Postgres, but it’s also on top
of Postgres extensions, and it’s not necessarily a new database. You can put it on existing database, and you will have, or GraphQL API automatically generate it for you so it’s a really nice thing. And even, if you have, let’s
say, Firebase, or MongoDB, you can use a bunch of
tooling when you have to convert from NoSQL
database to a Postgres ’cause running migrations. So I have lots of features,
and I actually streamed that, I think two weeks ago, the overview of capabilities
and stuff like that. – Okay. – So the idea for today
basically is we will create, right now, we’ll create the GraphQL API. We will create some kind of blog post app, local CMS, something like that. And then, we will create
frontend with Gatsby and connect everything or have realtime updates in the app. So to get started, just scroll up. Yeah, so you have the Heroku Free Tier, Get Started With Heroku Free Tier. It’s just the easiest way to get started. If you go down, you will
have Deploy to Heroku so you just need to
click Deploy to Heroku, and yeah, you need to log in. – Okay, let’s see if I remember. – Yeah, I think you need
to remove it from the view or something like that. For passwords and stuff. – Yeah, I think I have. I think I can just copy/paste this. Let me– – Oh, okay. – Yeah, here we go. All right. – Yeah, that works. – So let’s get in here.
– Okay. So basically what it does
if you’re not using the URL, there will be a Heroku schema that is passed to Heroku dashboard so you can create, wait,
Hasura Gatsby already exists so you need to change app
name to something different, add demo or something. Yeah, and it automatically
adds Heroku Postgres add-on. So now, if you click on Deploy App. – Nice. – I think it’s one of the
fastest deployments of Heroku I’ve seen so far. (Jason laughing)
So I think we’re already ready if you scroll down. – Oh, wow! Oh, I didn’t even realize
that was happening. Okay. – Yeah, it’s already happening. And you see, it’s already there. So you can click on
Manage App or on View app. So Manage App will bring
you to Heroku dashboard. You can go through settings and
all the Heroku stuff, right? But you can go into Open app. If you go to Open app here, it will actually bring
you to Hasura Console where you will be able to create basically your data in Postgres and get auto-generated API and everything. – Oh, come on. – Yeah. I think it’s deployed but it’s. – Let’s see. It shows. – It’s still updating. I think it’s live if you get through it. – There we go, okay.
– Okay. So this is the console, right? And it has four tabs
for four major sections. So right now, we’re in
the GraphiQL section which is pretty familiar to everyone who use GraphQL, right? – Mm-hmm. – It’s actually GraphiQL on steroids. So it has regular GraphiQL capabilities, so you can have in-browser
ID for your GraphQL queries, and if you, for example,
click on Docs on the right on the GraphiQL, and
inside the query root, you will see nothing because you don’t actually have any data. We haven’t created even one entity. So let’s actually do that. So you can go to Data tab. And here is where you
basically start creating stuff. So let’s create a table. Name it posts. – Okay. – And we’ll have id, just name it as id. And you can select your ID. – Okay.
– Yeah. And you see in the example
on the right field, you have gen_random_uuid. It’s a helper function. You basically, if you write
this down as a function, so if you do gen_random_uuid. Just try to do that one. – Do I call it as a function? – Yeah, yeah, it’s a function, so it will generate
all unique identifiers. Now we’ll have, let’s say,
title and will be of type Text. – It doesn’t need a default in that. – And now we’ll have content. – Okay. Also the type of Text, and I think we also need
some kind of user, right? So let’s create the user ID. Let’s try it as user_id. And if I have a type of unique identifier, and we won’t generate that ’cause it will be in a
different table, right? So you need to select the
Primary Key and then– – That’s what we want, right? – Yeah, we’ll want only id, and then if you click on Add Table, it will not only create this table, it will also, yeah, so it’s created. You can browse rows, insert rows, just like a regular phpMyAdmin
or pgAdmin type of UI. If you go the GraphiQL, you
see already have queries and mutations and everything. – Ah, cool. That’s very cool.
– Yeah. – And mutations–
– And you have not only if you click on query or mutation, you see it’s not only just
plain queries and mutations, they also have additional things such as distinct and the offset and you can actually add where it closes for being able to query or filtering stuff and negating aggregations
with the sum and come and stuff like that. – Yeah, can you talk to me a little bit about what an aggregate is? ‘Cause I’m not familiar with this term. – Yeah. So if you click on aggregate,
so the output type, so you will have nodes which
is basically your data, and aggregate will have
count, maximum, minimum. That’s the main idea. So if you wanna count stuff and just get it from the query, you’ll be able to do that
right from both in these files. – So you mean if I’m trying to find all posts tagged with a thing or all posts by a given author, I would use an aggregate
query, or would I– – No, it’s mostly, if you want to get the maximum amount of post
with some, where close. So you want to get maximum
posts of specific author or something like that, yeah. Then you will use aggregate. – Okay, and then– – And this is posts by primary key. It’s basically querying specific posts. So if I want to get data from computer. – Oh, gotcha, okay. Cool, very cool. So then we– – So now, if you go to, get back to GraphiQL. – Okay. – Yeah. What just happened? Can you reload it for a second? Okay. I think you accidentally
deleted the table or something. You can get it to data. – Oh, how would I have done that? – That’s weird. – Okay, I guess we’ll do it again. – Yeah, okay, let’s try to do that again. – All right, so that’s UUID, and that’s gonna be gen_random_uuid. We’re gonna do a title,
which was text, and a– – And content.
– Content, which was text, and author_id. That was a UUID. And we’ll make this an id.
– Add Primary Key. – Okay, so that should give us our table. – Yeah, okay, that’s fine. So right now let’s create another table and let’s call it… Yeah, click on Add Table.
– Add Table, got it. – And then it will be
like authors or something. – Okay. – Yeah, right now it will be
also id, unique identifier, and let’s say we’ll have, I
don’t know, name, first name, first name, last name, or
maybe avatar URL or something? Oh, let’s just skip it with the naming. – Yeah, let’s just do.. Yeah, I need to change that
first name and the last name and I think we can
probably call that good. We’ll index it on the UUID. Gen_random, oh, that’s my fault. – Gen_random. – Okay, so now we have author and posts. – Okay so now it’s better,
now, the interesting part, if you go to GraphiQL tab, for example, if you try to go to query, for example or just query things, and you
will have authors created, but if you will go into posts output, you’ll see that we have author_id which is contradicts what we
are used to in GraphQL, right? We want to get the authors
and everything, right? – Sure. – So that’s because we
need to set relationships between two tables, right?
– Okay. – So let’s get it to data and go to posts. – Posts. – Yeah, Modify. – Modify. – Yeah, now, if we
click on Edit author_id, we need to change basically
add the foreign key. So it’s all the way down.
– Ah, foreign key. Authors.
– And you reference author’s table and id. – Okay.
– So if you click Save, it will actually suggest
to create a relationship, so you click on Add relationship. And if you miss that, it’s
in your Relationship tab. So right now, it suggests
how it will be named in GraphQL response, right? So we’ll name it author,
so you just click on Add. – Okay. – And, let’s name it just author. So right now, if you go to
GraphiQL tab, for example, and see the output of posts, you will see author there, yeah. – Oh cool. – Actually, if you go
to authors, for example, it will suggest you to Add. No, if you go to DATA.
– Oh, I got you. – And authors, just
click on relationships. It will suggest you an
array of relationships. For example, you want to
get old posts for an author, so you want to connect it from there. So you can name it posts, and
now from the author’s query, you will be able to get all author posts. – Well, that’s pretty slick. Okay, so, oh yeah, and then
I just do the same thing. – Yeah.
– Okay. So now what? Should we add some posts or? – So what we wanna add additional stuff, we want to add comments, right? – Hmm, that’s right. – The main idea will have posts, people build populated
on Gatsby build, right? – Right.
– And we want subscriptions to be for comments. So let’s create comments with ID. And we will actually have another field, post_id, for every comment. – Okay. – And we’ll have author_id, right? – Do we wanna make it that complex or should we just have
an arbitrary text field? – You mean just doing it without? Yeah, let’s do it just without authors. – Okay, yeah, we’ll just do that, ’cause I think otherwise, there’s a couple relationships
that’ll be a pain. – It’s actually not that complex, because, well, primary key is still ID. Actually, let’s do it with an author ’cause it’s pretty simple
to refer from the UI here. – We’re gonna do it with an author id? – Yeah.
– Okay. – So right now, you
can remove it later on. If we’ll see if we’ll
take time to do that. – Okay. – We’ll just move it later on. – And then now that I’m in here, I’m gonna add relationships, yeah? – Yeah, yeah. – Maybe I can do it ’cause this one– – Yeah, Modify, and then
add the foreign key. – Id, let’s add the relationship. Author.
– Yeah, we’ll name it author. – Okay. And then if I go back to
Modify, I can do the post. Oops. And we’ll do a foreign key for the post. Do we not add the post id? Oh, no, that’s my mistake. – Yeah, the post id.
– I’m just confused. I thought we were looking
at the comment table there for a second. Okay, so then we’ve got posts. Or this would just be post, yeah? ‘Cause it’s just the one that is just– – Yeah, it’s just post ’cause
it’s all just relationship. – Okay, and then– – Okay, I think it will be fine. So let’s add actually a new post. So the thing is we need to
provide a user ID, right? Mutation that we need to
do is insert, insert_posts. We will insert both posts and authors in the same mutation actually. – Okay.
– So we add objects. – Okay. – And it will be an array, objects that we can add. Yeah, and inside, if you open, yeah. It will be easier.
– I’m just gonna look at this along the way here. So we’ve got an author. – You forgot the curly braces. – Oh, yep, got it. So we’re gonna do an author, and– – Yeah, so the author will
be a little bit different. So it’s a neutral type of data. So you need to provide it a data because we want to actually create two entries in the same mutation, right? We want to create post and
we want to create user ID and command them in just
one single mutation. – Okay.
– So right now for author, we need to add name. What was for the author? – Is it gonna let me do that? It looks like it doesn’t have the– – Yeah. Oh, wait. – Am I missing things? – I think. Have we added name, first
name to the author statement? – I could have sworn we did, but. – I’ll just get into Modify. – Did it dump that table again? – That’s weird. (chuckles) – Okay, or is it doing
what we want it to do? Id posts, yeah, it’s
not saving everything. ‘Cause we’ve lost our. – Hmm, now that’s weird.
– Okay, so– – The first time we haven’t, and actually we haven’t
any release or something. – Yes, okay so this, this is right. – Okay, this is right. Now actually, it’s not a tile, it’s title. – Okay. That’s probably just a typo on my part. That’s fine. – Ah, okay. – But yeah, the comments table. – Comments, it’s fine.
– Dumped. Well, it dumped its content. So let’s save that. Hello?
– I think just reload that. Just reload the UI maybe. – Okay, reloading. Let me do a hard refresh, make sure that we get everything. Okay, so we’ve got id,
post_id, and author_id. We’ve got– – Yeah, that’s all.
– And the host. It didn’t save my typo fix
for some reason so let’s save. Okay, so it says it was modified. Let me hard refresh again,
make sure that’s still there. All right. – I think it might happen because
we’re switching tabs fast. – Okay. – Maybe because like we change the date, we get to GraphiQL, it hadn’t saved yet. And yeah, that might be the case. – Okay, so column modified and now we need to add–
– Okay, let’s add first name. – First name, last name.
– And last name. – Column added. Okay. – Okay.
– Do the hard refresh. – Yeah, let’s– – Make sure everything’s still there. Okay, so it looks like it’s
holding onto our changes now. – I think it was just switching
tabs fast or something. – Okay, all right, cool. So let’s– – I think because we created
first name, last name, and then we switched
to GraphiQL from there. Well, when you add the table, you will see a red bar
on the top of the UI and it’s basically the creation thing. Probably if we switch
in the middle of that, that it won’t say error fixed. – Okay, so here–
– Yeah, so we insert post. We also need to add objects. We added author, but we need
to add a title and content. Try it for the post. So let’s enter that. Now it’s in the same object as as author. – Here, like the–
– Yes, yes. – Oh, title?
– Yeah, yeah, yeah. – New post and content. Did it not save our content again? – No, the content added
just for the comments. – Yeah, our post seems to
have dumped its content again. Okay, let’s save this so
that we can get some content. – Yeah, and then we need
to return something. So we have returning or affected rows. Let’s return an id, and author id. – Okay, so we can run that. fieldName, firstName, not found in authors_insert_input. – First name. – Insert_posts. Author–
– These things happens only with live coding, right? (Vladimir laughs)
– Yeah, that’s. – No, it’s here, so first name here.
– Okay, first name. Did I spell anything wrong? First name and last name. All right, let’s try that one more time. No, all right, I’m gonna save this. Let’s refresh the page. Look at it again. Oh, it fixed it for us.
– Ah, yeah. – Okay. – You know what? It might be because of the
naming if I think about that. Now it’s the same. – Field title is not found in– – Ah, field title. – It dumped that typo again. Okay. Let’s try this again. Okay, so it at least at this
point has saved something so let’s go back in here
and let’s look again. Yeah, it keeps dumping. Let’s do title. Save that in this– – We are worried what gives them that. Let’s try for a second. – Sure, what?
– Let me change it. Happens to me too. – Yeah, let me see if
it’s, is it doing anything? Maybe I’m getting a bunch
of errors or something? Okay, so nothing’s changed there. Do I have logs? – So I’m trying to do the same. – Build blogs, don’t need those. I guess I’d have to add full on logs to see if something’s
happening, but let’s see. It has now had some time to think. Let’s refresh this and see if it kept it. It says it kept it. – Oh. – (chuckles) Somebody’s messing with us. – Yeah, I think something’s
weird happening with the Heroku when we set it up first. – Yeah, it also looks like somebody’s just in here playing too, because we’ve got an open endpoint so maybe we should secure this first. – Yeah. (laughs) Actually, it might be
the case, by the way. So yeah, click on secure endpoint and then you will have For Heroku. – For Heroku. – Yeah, you need to basically add HASURA_GRAPHQL_ADMIN_SECRET, so just copy/paste some secret into– – Okay, let me pull this off screen. – Here are the secret keys. There was the second there. You can actually show that
before facing the actual start. – Okay, yeah. That’s probably a good call. Okay, so what I did is I
went into Settings here. And I’m adding this, and then I’m gonna put a value in here and it’s gonna be a secret
that nobody can see. So let’s do something that I’m going to… Okay. So I have added it now, and it’s hidden and then
now that I’ve got it, setting this environment will automatically restart the dyno, which means it should be starting now. – Yeah, now you can refresh there. No, no, not here though,
the actual console. – Shouldn’t it have restarted though? – No, if you basically restart
the console right now, no. – Oh, okay.
– Just go there. – Okay, let’s open the app.
– Yeah, open up. – And it will ask you for secret. – Ah! I’m just gonna move this
off-screen just in case. Okay, it did, in fact, work so let me drop this in here, all right. So now, hopefully, (laughs) this is gonna
stop playing around. Okay, so let’s go back
in here and look at that. – In any case, I’m already
created the same thing. – Okay, so we’ve got author. – Nice, first name is
securing your import. – Yeah.
(Vladimir laughs) Post_id, author_id, content, and here we’ve got ID. – Title, author.
– Title, author_id, and content. Okay, so hopefully after this, it’ll stop messing around, so let’s– – At this point, we actually don’t need the security endpoint thing so
we just can drop this table. – Okay, so let’s drop this table. – Yeah, we’re going to modify.
– Which I will modify. – And we’ll have the table. – Delete table. Then, okay. All right, thanks. Thanks for teaching us a
lesson, viewers of Twitch. So, okay, let’s go back in here and then maybe what we can do is let’s, just to play, let’s modify this author. And so we’ll do mutation,
modify, update_authors. – Yeah, we have updated those. – And that’s gonna be our where. – That’s. – ID.
– Yeah, it can be where and then it can be said, where with ID. – Oh, is it like an equals kinda thing? – Yeah. It’s an object and then equals. – Equals. – Underscore equals and then id. – Oh, I need to change it up here. – You actually added in something, yeah. So in the underscore, set– – Set firstName to Vladimir, lastName to Novick, and we’re going to returning. – Effective, yeah, we can
return an id or something. – Yeah, all right. And let’s return the first name
to make sure that it takes. Okay.
– Okay, that was. Yeah, I think it was because a bunch of people tried to play with you. (both laughing) – Well, that’s what we get. – Actually, the problem, that’s why you need to secure
endpoint first thing, right? Because if lots of people
trying to get into the console, even at least another person
tries to get into a console and you do both of you do
the stuff on the database, yeah, that’s what you get. Secure your endpoint as a table. (both laughing) – All right, so lesson learned. Okay. I think, at this point,
we just have an author, we don’t have any comments. We have one post.
– Yeah, we have only post. Let’s create a comment. Let’s subscribe to
comments creation actually. Let’s see how subscriptions work. – Okay, so I’m gonna
subscribe to comments. – Comments. Yeah, just for the content. – Okay. And do I? – I think the best way is
to open a different tab for the same console and show them, if you can show two of
them on a split screen. – Okay, let’s see if I can do this. I have a goofy setup for
the live stream where my– – Oh, okay.
– My window is very small. So let me take this, and
then we’ll go over here and I’ll make this one smaller. Okay. Oh, come on. This one and this one. Okay.
– Okay, nice. – So that should give us the ability to, let’s do a mutation and– – Do we have insert comments? – Insert comments. – Let’s add a content. – Okay, and the content
is This is a comment. – But we actually need
a user ID and post id. – Okay, so we can get those from– – From DATA. – All right, let me grab over here. I’m gonna go to the author. Okay. So go back here. We will set this one and then we’re gonna set this on a post so we’ll go back again
and get this post ID. Nope, this goes–
– No, it’s enough. Yeah, it’s fine. – And come out here. And when we play this–
– I need to re-exam something here. – When we play this, what should happen is this should show us a comment. – Yeah, that’s right. – There we go. – Nice, it’s working.
– That’s it. Yeah, nice and–
– So that’s basically what we want to add is realtime data in our Gatsby front-end, right? Yeah, so I guess let’s set up Gatsby and connect it to– – One quick question here that
came in through the chat is, Wise Because asks, “Would two devs be able
to work at the same time, “but in different tables?” – Good question. I’m not sure. (chuckles) I’m not sure to answer that. It’s advised not to do that. – So it seems like probably you wouldn’t. This would be like if you
were working in WordPress or any other thing, if
you save to the database at the same time as somebody else saves, whoever saves last is probably gonna win. – Yeah. I’m not sure. I’m actually not sure
what will be the outcome. Maybe if you will get secure your endpoint as they was we had that.
(Jason laughs) On the different tables, it
might work without a problem. The thing is, when you add relationships, then when you start going across tables, and especially if you set permissions, I think just adding simple
data in two different tables or just modify things
will work probably fine. The thing is, it won’t be live updated, so the other dev have
to reload the console. Collisions can happen because some person wants
to reload the console. Basically, it’s not advised to do that. – Okay, yeah, I think
that’s a safe answer. Probably don’t. (laughs) – One thing, though, because
it’s a Postgres stride, so the advice use case
for working in production, you obviously need several
people to work on database so basically, you don’t work for console, you just work on an actual database. UDDA does stuff on database, right? The thing is, the engine
will auto-generate GraphQL over existing database too so
if you just add a new table, just a Postgres without
adding it through the console, it will still generate queries
and mutation subscriptions. So you can simply work
from pgAdmin to add data and manipulate data there. Or use the console mostly for permissions, connecting between staff
and stuff like that. So if you need to work
directly on the data, then probably you’d do
it just through Postgres or something like that. It actually brings me
to one important thing. If you go to DATA for a second. – To the DATA tab.
– So you go to the native data flow. You see that SQL, SQL on the left side? – Mm-hmm. – If you click on that, you actually can write your custom SQL. – Oh! – The cool part, if you create a view, or if you create a function– – Can I still do this?
– Then you will be able basically to… Let’s just create a view from that one. Yes, we’d like to execute
the one we’ve done. – Oh my god, I can’t
believe I just remembered how to write a SQL statement. (both laughing) Okay, tell me where was the View button? I don’t see it. – Yeah, the idea is, if you
create a view, a SQL view, so you will do create,
view, and stuff like that. – I’ve never done this. You’re gonna have to walk
me through the syntax. – Yeah, to be honest, I don’t remember. (both laughing) Pretty much that.
– Let’s look it up. – If I remember correctly is create view, view name as, something. – Create view.
– And then select. Yeah, it’s been a while. (laughs) – Okay, create view. – Yeah, view as.
– As. – And then–
– Okay. So if I do testing as select. – Select. Start from, yeah, everything from posts. – Okay, and if I run this. – You see, you have a
testing on the left side. – Oh, fascinating! So we could–
– Now the cool part, if you do it with GraphiQL.
– We could pull it just like that. Okay. – If you go to query,
you’ll see a testing query. – Oh, that’s cool. – Yeah. And you can create SQL
functions with mutations so it’s also a really cool thing. Actually, if you great SQL functions, it will generate mutation for you. – Yeah, that’s pretty slick. It’s been literally years
since I’ve done any DB work so, I have no idea what’s possible. The last stuff that I was doing was just writing MySQL statements
so this is pretty cool. – The cool part that you
can actually tell your, you see it, you have Analyze
button here in GraphiQL, right? – Yeah.
– Yeah. So this one won’t give you
anything, but if you query, let’s try querying
something, just query posts. – We’ll do content.
– With content something. Yeah, so in the pink one–
– Uh-oh. Oh, that’s right.
– I noticed about that. – Because we didn’t add any content. That’s right. – Yeah. So actually–
– Oh, fascinating. – Yeah. Actually, the engine compiles. Instead of just connecting to database and stuff like that, well,
it’s still connected, but what it does, it
compiles to SQL query. Instead of just doing your custom result or it basically compiled
your GraphQL query to SQL. Only for queries, right?
– Yeah. – And executes them on the database. So you can, for example, copy
this and send to your DBA and it’ll ask, you know what? I’m not sure if it’s performant
enough for my use case. He’ll probably tell you, okay, yeah. – Oh, wow. – He will probably tell you, okay, if it’s not performant enough, let’s create a bunch of
views, let’s do DBA stuff. Because you can track these views, you can add these as track view and then query this view instead of querying the actual
post table or something. – That is intense. I haven’t looked at–
– Yeah. – Whew! This makes me happy that we have GraphQL. (laughs) All right. So I’m glad that the folks at Hasura did this so I don’t have to. And then another question is, as we go through building this, are we gonna do error handling as well? Just ’cause somebody was asking me if we’re gonna take care of that. – I think we won’t have time
today to do error handling but we’ll catch this–
– So that the default, though, so if I just do a bad. Let’s do an insert posts, and– – You have a lethal error
with the very descriptive. Yeah, just run it as it is. Just run it like that. – If I try to add nonsense data, or I guess I should do something. Return the ID. It gives you an errors object at the top and that errors object is
gonna tell you what happened so it’ll let you know
where things went wrong. – Yeah, that’s right. – But yeah, so typically speaking, you could just look in your app for if there’s an errors on array. Then you can read into that and figure out what actually went wrong. – Yeah, and you will have a bunch of codes for different error handlings. So you will have validation
failed or type wrong, and stuff like that, so you can basically
put the error boundaries or something like that, and
then treat it accordingly. – Cool. So yeah, I’m gonna just jump
into the Gatsby side of things. I’m using the Hello world! starter to give us just a bare repo, which means it’s not gonna look pretty, but there’s not gonna be a
lot of boilerplate either. And let’s see here. So I’ve got just the very basics
of Gatsby being installed. It should take a second. Computer always runs nice and slow when I’m trying to stream, so
makes these look even slower. Come on, all right. So we are sitting at a clean branch and I have already opened it over here so that we can take a
look at what’s in here. So what we’ve got is right
now the Hello world! starter. Got nothing in it except this very simple Hello
world! React component. So, what do we need to do here? Is there a source plugin for– – Yeah, I think when it
does the source plugin to be able to query our
posts on a build time. – Okay. Do we use this or do we use the Postgres? – No, just drag all of
that to the source plugin. gatsby-source-graphql. – Oh, gatsby-source-graphql, okay. So gatsby-source-graphql, and we’ve got it here. So the trick is gonna be to just run this. And once we’ve got this installed, I’m gonna go in and configure it, which I can start doing now. We’re gonna create a gatsby-config.js. I’m gonna delete this
yarn.lock because I’m using npm and I’m gonna have to remember not to put my muscle memory do yarn. Okay, so we’re gonna do plugins and in here, we’re going to do resolve for gatsby-source-graphql. And for options, we need
to look at the docs. – Let’s do typeName Hasura in fieldName. – Hasura, fieldName. – And fieldName will be
another post or something. Oh, no, not post actually, blog. – Yeah, we can do that. And then the URL.
– We need to create a link. – Is going to be– – No, we actually need to create lin because we need to pass headers, right? We need to pass authentication header. – Oh, we’re doing it straight up like this?
– So basically, yeah. Yeah, this time.
– I understand. Okay, so let’s graph this out. – So we’ll also need to
install a following HTTP. – Okay, so let’s do this. So I need createHttpLink which
is going to come out of– – You can just install ApolloBoost. – ApolloBoost.
– And then you’ll have it at once. – Okay, so npm install apollo-boost. I don’t think I need to do that anymore, but I’m gonna do it just in case. Okay. I need to pull in an the
isomorphic-fetch too, right? – Yeah. But not here. We need to basically create a gatsby-browser and database now. – It isn’t asking me to pass this in, or? – Ah, it can be. Yeah, it can be isomorphic-fetch. It can be also node-fetch actually because it’s gatsby-config, right? – Yeah, okay, I’m just gonna pull it in because we’re gonna use it elsewhere and we’ll just use the
same fetch everywhere. And what isomorphic-fetch does is it poly fills between
the browser and node so that you can use
the same fetch function without worrying about it
failing in server-side rendering or working in one environment
and not on the other. Okay, so that means I need
to then come back over here, and I’m going to get fetch from isomorphic-fetch and I’m going to get createHttpLink and that is apollo-boost, and then is it createHttpLink like that? Nope, that’s not the one I wanted. HttpLink. I don’t actually remember if
that’s the way that that works, but we can give it a shot and see. And then I need to create. – Yeah, so in headers
basically, we had this header. It’s Hasura-Admin-Secret, right? Yeah, this is going. – So I’m gonna set this here and then I need to set this to be, we’re going to call it the same thing that
Hasura told us to call it. So I’m gonna pull this off-screen so that I can see that token again. – But actually, we can
use it as Admin-Secret, or we can use it as Hasura-Access-Key. Both will work. – Hasura-Access-Key, is there– – You don’t power as
authorization as bearer basically. – Okay, is there something
that I need to do differently? Is there a key or do I use the– – Yeah, so in the key, you see that as
X-hasura-admin-secret, right? – Right. – So if you go back to
your createHttpLink, yeah, so in headers, the name will be X-hasura-access-key or admin-secret, both will work. – Am I looking at the wrong line? And then the admin-secret
is gonna be the one that– – Yeah.
– Okay. And so that’s not a bearer token. It’s just a regular old secret. No.
– So I’m gonna save that. – Just for our site, that
obviously at some point, when you do authentication,
it will be about token but it will be like Hasura supports the various types of authentication. You can do JWT, you can
make stuff with Cognito, if that’s what you’re playing, Auth0, custom of anything literally. – And so what we wanna do here is you’re gonna create a dotenv
file with your admin-secret. I am not going to show
that because clearly, you and the audience
cannot be trusted. (laughs) So I’m gonna do this off-screen. I’m gonna create a copy of the dotenv to just a regular dotenv file
and you’ll see that pop in and then I’m going to
just edit that real quick. I believe that’s what it was. Yup, that’s right. Okay, so I’m gonna save this and now I’ve got a dotenv file setup which means that in here, I can require dotenv and run a config and that means that
we’ll have this in our, it’ll be available to us. I’m gonna put that lower. So I believe now we don’t
need that plugin option, we’ve got fetch, and we’ve
got everything set up so let’s run this, bring this back over, and now I’m gonna run gatsby develop. – We’ll have pages and stuff in this– – Oopsies, what did I do? – On second thought, it’s here so. – Type it bad. – 22nd line.
– Oh. – No, it don’t. – Touch, there we go. All right, I was missing a curly brace. Okay, try that one more time. – So we have pages– – Oh, come on.
– Set up, right? Okay, what’s wrong? – createHttpLink is not a function. Okay, I imported it wrong so I need to actually look this up now. – Yeah, just go back, I
will walk you through. – Oh, okay. – Yeah, so it’s createHttpLink from, it’s from apollo-link it should
be, not from apollo-boost. – But I didn’t install apollo-link-http. – Yeah but we’ll just install it. – Gotcha, okay. Let’s try that again. No, we’re.
– Oh, it’s not. Probably it’s not. (laughs) – Okay, so ApolloBoost. – Yeah, so just install
apollo-link-http separate than that. – Okay. – I was pretty sure it installed but I guess it’s like muscle memory when I write it, I kinda
installed it, and not thinking. – apollo-link-http? – Yeah. – Okay and that’s what
I’m including and what’s– – It’s a named import, so. – A named import, okay that would also be part of what I was doing. – And you included defaults. – Got it. Okay. We’re gonna get there. All right. You got it. Let’s run this again. That’s actually the first
time I’ve ever set up an HTTP link inside of
the Gatsby GraphQL setup so let’s jump in here and
what we should have now, assuming all went well,
we should have a blog. – Blog, yeah. – And under blog, I should
be able to do posts, and under posts I should
be able to do title, and that gives us our post from Hasura. So that’s pretty exciting
that that just works. – Yeah. So what we can do right now is basically yeah, we can create
these pages like post date. Does this author has simple
pages set up if you go to so, yeah, okay, so our index page, basically it just have a world. Wait, let’s export the query. – Okay. Yeah, let’s do it. So we’re gonna export query, that’s gonna use GraphQL from Gatsby so we’re gonna need to
import that from gatsby and then in here, we can do
what we just did out here. – It’s below this one. – And we need the content and the author, first name, last name, and I don’t think we ever set up the relationship for comments, did we? Let’s get maybe this part running first. – Post. Yeah, I’m pretty sure we did not. – Okay, so this is gonna get some data– – But you know what, let’s
bring these data first and then we’ll deal with
we’ll deal with comments. – All right, so we’re going to have, let’s just do a div. We’ll add a little bit of
style to make it readable and we’ll do this and auto and we’ll make the width,
I guess the max width. No, we’ll just do the width. This is I think everybody’s
favorite part of my stream is watching me write CSS. (Vladimir laughs)
Let’s do 550 and that’s going to– – Actually, there is a
CSS medium list framework that I typically use for
these type of things. – Yeah. (laughs) I should absolutely do that
and I definitely have not. Posts and then we’ll do a map
and that’ll give us a post and in here we can do a,
oh, we need to get the ID so that we’ve got a unique key and we’re going to do a… We’ll just do a article. The key is going to be the post.id and then we’ll set the post.title and I think that’s every, er, no. Will be written by post.author.firstName post.author.lastName. And that should give us, let’s see. post.author.firstName and lastName and then for the content, I don’t think we actually
wrote any content. Let’s just not use the content actually because this is a preview page. We’re not gonna stress about it. So let’s go in here and
we’ll go to localhost:8000 and we get our post.
– Okay. – So let’s maybe create–
– Cool. – Create a couple more
or one more at least. – We can do it from UI but here we’re dealing
with forms. (laughs) Yeah, then we need to wrap
it with ApolloProvider and do it tomorrow. – Oh yeah, let’s maybe save
that just for the comments ’cause I think it’ll get a little, especially if we’re gonna finish this in the next 30 minutes. We’ll just create the row manually. We’re gonna create a
title of another post, the author ID that we want is, let’s see, we’re gonna have to pick out one– – You can pick out the others. – Authors. Let’s grab this. – And if we’re already here, let’s set up relationships
for posts and comments. – Okay, so we’re going to insert row. – No, to our relationships. – Oh, yeah.
– Ah, yeah, you interpret, so yeah. – Let’s do this. Inserted, okay. So we’ve got our row, let’s
go to our relationships and let’s add another one on the comments. – At Suggested Array relationships. So you see I haven’t set up
any foreign key or something but because you said from
comments you said post ID as a foreign key to post, you haven’t suggested a
real relationship, see. – That’s really nice. Okay, so let’s do that and that
should give us what we need and then I guess actually
this is a good excuse for us to use the comments_aggregate, wouldn’t it be? Is there a– – Yeah, we want the
number of comments, right? – Yeah, and we don’t have that set up but I guess we could do, well, how would we wanna do that? – Oh, wait, wait. We can actually do it here so let’s do instead of comments, yeah, we actually need it as
a separate query, I think. – Let’s see, I’m gonna start closing tabs ’cause I have many tabs here. – I think so. Let’s try that actually. So you have Add relationships manually, so if you click on that, we have an array. – We want the count, right? So we want the number of comments so would it be an object? – Yeah, yeah, yeah. – Okay, so the configuration,
it’s gonna be commentCount. – [Both] Comments. – Can we get the count? No. – No, I think it won’t
get us the aggregation. We need to in a separate query. – We need to create a view
or something, wouldn’t we? Okay maybe that’s– – We can create a view, but
we can actually have the… Yeah, we can create the view but then we need to recount
in the SQL basically and then we can add that as a table, as made on relationships. But yeah, I think it’s
too complex for now. – Yeah, a little out-of-scope
for what we’re doing today. Okay, so let’s– – But we can do another query here. We can pull comments and we
can pull comments_aggregate, so under blog, blog– – Oh, I’m gonna wite it in GraphiQL so that we get the auto-complete. Oh, nope. – No, it’s not here. – comments_aggregate.
– comments_aggregate. – And then we get–
– And we’ll get aggregate. – Count.
– And a count. – Okay so that will give us– – And maybe rename comments_aggregates to something more readable I guess. – Okay, so now the only
catch here is it shows me one but it doesn’t seem to be limited by post. It’s just total comments in the table. – Oh, okay. I got it. So if you want to get
the specific comments for specific post,
basically what you can do, you can basically these comments will be, it will be dynamic
subscriptions anyways, right? So for every post, we basically have, instead of querying our post, we can query post by primary key and then inside post, we have a comment. Ah, it’s still not aggregate. Okay. – Let’s not fixate on that. That’s something that we
would like to fix but– – No, actually we can do
it with comments_aggregate in WHERE clause basically. – Okay. – When we get into the post for example, we’ll get the post ID, right? – Yeah. – And then we go comments_aggregate, so if you try to do
comments_aggregate here. No, not here on the
higher level under blog, comments_aggregate and
you have WHERE clause, so you can basically query by post ID. – Right, so we would put
the post ID in there. – Yeah and that will
get you the actual count for post comments. – Okay, cool. And then on the post,
we should have comments but I am getting… It doesn’t look like the
remote schema has updated here so let me do a refresh. – Because we need to rebuild. – Yeah, I stopped and started and I think I might have
just not quite gotten that. Yeah, let me stop, let me do a– – Maybe cache? – Yeah, remove the cache
and let’s start it again. Comments is a subfield so
now it’s actually working and that’s what we wanted. Okay. – Boom! – Cool, all right. Yeah, that’s great. That’s kinda what we wanted and it’s showing us our
post and the comments. So here in the front post, we have just a list of what should be. Yeah, posts. And then if we wanna make
those posts accessible on their own pages, we
are going to do a… Not there. I’m gonna set it up down
here, a gatsby-node.js. Inside of this, we’re going
to exports.createPages, createPages is a function. It’s gonna accept some actions, one of the actions is gonna
give us this createPage and in addition to createPage, it’s also gonna give us a
GraphQL helper function. So let me collapse this down
so we can see what’s going on. I’m gonna make this async so we don’t have to write promises. Sorry, that async needs to go back here. Okay. And then I have a function
and in my function, I am going to do the
results is going to be the awaited value of this GraphQL and the query that I wanna send
is going to be very similar to this one that we wrote out here except I don’t need the
title in the comments or I’m just gonna get the title and I’m gonna build a
slug out of these titles for the sake of easy linking. That should give us that and then I’m going to set up
a to-do for error handling and then assuming that that worked, we’re gonna do posts
equals result.blog.posts and then we can do a
post.forEach, get a post, and down in here, we can do a createPage and we’re going to send a path which is the path that we
want the site to pick up. We’re going to set a component which we will have to
create here in a second and then we’re gonna set context and the context we’re gonna
set, we should include the ID because then we can query by the post ID. And maybe what I’ll do actually just for the sake of not having
to write a helper function or import another library is I’m going to just use the post ID as its path, so these are gonna be really
ugly URLs but it saves, it helps us get this part done without having to write helper functions. So let me create a template for this post and that’s going to have React, we’re gonna import React from React, we’re going to need a query which we’re gonna have to write and then we’re going
to export a component. The query, let’s get GraphQL from Gatsby, and the query that we wanna write is going to include a query variable which is going to be that ID that we got from the context here. So we want this ID. And then we’re gonna use that– – It’s UUID though, the type. – Oh, is that the type? – Yeah. – Fascinating! I didn’t realize that
it would pick that up. Oh, hasura_uuid. I need to make that even more. All right, so that’s gonna be hasura_uuid. Okay. And then I’m going to make
a query for blog, post. What do I do if I have– – Post by primary key.
– Post_by_pk. Posts plural. And then the ID is going to be equal, no? Or just this?
– Yeah. – Okay. So let me go grab one
of these so that we… Posts, Browse Rows, let’s
edit it, let’s grab this, come back out here, toss it in, and we should be able to
get the title, author, and we’ll do first name. So that gives us what we want which means we can take this out and drop it in here and then swap out this string here for our query variable and that– – I think we have too much curly braces in or I might be wrong. – One, two, three. One, two, three.
– Oh, okay, fine. – Yup, okay.
– Yeah. – So then we want the
first name and last name and let’s start there. So that’s going to give us a
data prop on this component. We can do the post equals data.blog. I’m gonna alias that. data.blog.post. And so then, for just making
sure that we did this right, let’s JSON.stringify the post and now we’ve got a component ready so we’re gonna
require.resolve that component and we want it to be
source templates post. All right, so posts, posts, okay. So this should be a functioning page. – Yeah, it should work. – Should give us what we want. Let’s run it again. Oh, looks like somebody noticed your background finally. (laughs) They asked if it’s the
International Space Station. – This one, yeah. This one is different. (both laughing) – Okay, and so I’m just gonna
break this so that we get. Oh no, I didn’t build our pages which means I did something wrong. Did we get an error? – Yeah, we have this can’t
read problem here, posts. – Cannot read property posts is undefined. Okay so I broke a thing data. – Data for some reason getting as empty. That’s what’s happening. – Or let’s log result
and see what happened. Oh, I already know what I did wrong. There’s a data prompt
that I didn’t include. So we get the the result
back and it’s data and then inside of that, so
data.blog.posts will fix that. So let’s stop and start it again. Okay, pulled things in, it
logged what we expected, but we didn’t get any errors which means when we come over
here, now we have our posts and the posts are loading
the data that we pulled in. Let’s grab the comments. The comment that we’re gonna
pull is just the content. – So with comments, there is
a controversial part, right? So when we get these
comments on build time, so we can give them on build
time and then add subscriptions and change them in realtime. So the controversial part is we will have, well, maybe it’s fine for this demo ’cause we will have a flip in UI because we will have comments that, let’s say we have two
comments in build time and user added 10 comments or something and remove several of them, and then when we will load the page, we’ll have these two
comments that were builded, brought on our build
time, they will be loaded, and then it will update automatically with all the relevant data. So I think in a real-world scenario, we will add some kind of, I
don’t know, maybe animations but we won’t do it right now. – Would another option maybe
to just not server-side render the comments and kinda load ’em in? – Yeah, yeah, it’s another option. We can just add there as
subscriptions and that’s it, then it won’t have any thing in line. – Let’s do that. So let me do a quick markup of this post and this is gonna be
really quick and dirty. Let me grab the the same
setup that we did over here and inside, we’re going
to do the post.title, we’re going to do written
by post.author.firstName, and post.author.lastName, and then we’ll put the
post.content in here. I still don’t think we
have any but that’s okay, and then I’m gonna do– – You have an error with like– – Oh, I do.
– The written by. – Okay. And we’ll call this comments, and I think we can just
leave that empty for now. So assuming all went
well, we’ve got that setup and I’ll just add, let’s do Link to home and I need to import link. Okay. So now we can go back to all posts and then I’ll do a quick
change here to include. I’ve got the ID so I can just
do a Link to post and post.id. Yep, and we’ll move this over here. All right, so that is not super pretty but it’s gonna do the job so we can get in and
out of these posts now, so we can kinda bounce around. So let’s get into this new post. This is the one that
actually has our comments and we need to do the Apollo setup. – Yeah. So basically what we need to do, we need to gatsby-ssr,
gatsby-browser, right? – Okay. – We need to basically wrapRootElement and adjust it for being render or right around server
on the plain, right? – Yes. So we can create a file called utils and we’ll do apollo.js and in this, we are going
to cheat a little bit and look at the Gatsby with
Apollo example that I did so that we don’t have
to reinvent this code, we can just kinda grab it from
a place that we know works. – I can just send it to
you ’cause I have it on. Well, or is it really excited. (laughs) – Oh, yeah. Actually, I’ve got it right
here so I can just grab this. – Oh, okay. – And let’s drop this in. The URI is going to be the one that we did in the gatsby-config here. And I’m gonna have to send that same. Let’s get rid of this, close this. I have to send the headers again. – Yeah, you can send headers. – Okay. So with that, that poses a
slightly different challenge because we need this
environment variable to be… Can I just do? Let’s see. I think this is not what we want because this is going to
expose that in the source code. Is there a read-only key or something? – No. The (audio becomes choppy) or complete to setup
if we wanted it to be. – Okay. We can do it kinda quick
and dirty here and then– – Yeah, and then just remove
it once submitting to it. – Yeah. This is not what you would
do for a browser app. You would wanna use something different because it would be– – This secret key is
just for playing around. It’s not for production app, obviously. We have authentication solution, you have data with dTalk and yeah, but that’s how you will work in a real-world scenario, right? But we’re trying to make
it super fast, right? In an hour and a half so. – Yeah, so we’re taking
a couple shortcuts here that you probably wouldn’t
wanna take in a real app. And so I am also exporting a
wrapRootElement constant here that just takes the… So we’re building an ApolloClient, we set up the URI, we set up
the authentication headers which you would change
to be kind of a read-only or a limited access key so that people can only post
comments or read the comments as opposed to being able to do everything which is what this would let them do. And then we set up that isomorphic-fetch so that it works both in the gatsby-ssr and in gatsby-browser. And then we’re exporting
a wrapRootElement function so that we can reuse this in both gatsby-ssr and gatsby-browser. So then down here in gatsby-ssr, I can do export wrapRootElement from util or source. What is it? Source utils Apollo and I can copy that and put the exact same
thing into gatsby-browser. And the reason you do both of these is one runs at build time and
one runs on the client-side. We wanna make sure that
it’s true in both cases. So that will give us our Apollo wrapper which we should be able to
see if we stop and restart. Here. Once this goes, we should be able to. Uh-oh. Can’t resolve React. Oh, I forgot to install react-apollo. – Yeah you need to install react-apollo. – react-apollo. And did I get everything else
that I needed to install? Let’s go to here. react, react-apollo, apollo-boost. Okay, that should be right. – What we’ll do right now,
we’ll add client-side query and then with subscriptions, we’ll add a bunch of follow-up widgets ’cause we need a bunch of
other repairing system, like subscription transport
and stuff like that. – Oh, come on. All right, so this is not
doing what we want it to do so I need to get the end variable out. I think the way that I can do that is by changing this to be GATSBY_HASURA. Let me try that in the terminal here. So then dotenv, and I’m
going to just prefix that with Gatsby Hasura. And I believe the way that
that works, let me just, if we look at env variables, what our docs say is if we prefix, prefixed with Gatsby will become available in browser JavaScript. So theoretically speaking,
this is just going to work. Let’s give this a try and let’s see. We got further but
something still went wrong. Can’t read property posts of null. gatsby-node line 15. Oh, and the reason is because
I forgot to update it here. Okay, one more try. Okay, things are happening. And I’m still trying to include the dotenv which would be the problem– I think the best way right now, it will be just like how
coding this in the file but not opening this file, just having it aside or something. – Okay, if this one fails
on me, I will do that. – Okay. – So this should have worked. – That should work. – And if I come in here and
we go and look at the React, do I not have the React DevTool set up? Okay. Let’s just not worry about that then. So instead what we can do
is we can come out here and we can look at this component, and this component sets
up just a basic query and so I am going to
grab the query component and the graphql-tag which
I think I need to install, so let’s install that. – You can actually use hooks but yeah. We probably won’t have time
for hooks right now, right? – Oh yeah, I would. I mean we can. It’s about the same level
of effort, I think, right? ‘Cause we just have to
install the ApolloBoost. – Yeah, and probably
wise ’cause basically, instead of react-apollo, you
install react-apollo-hooks. Yeah, this one.
– Okay. – And then you just use query instead of wrapping it in query. It’s pretty unique.
– Okay. Let’s see so. – Yeah, you just change the provider. – Oh, the provider. – To react-apollo-hooks provider. – Okay, so let’s do this.
– Actually, the readme is not updated ’cause yeah. – Let’s try it. I think we are gonna run
a little bit over today. Do you have extra time to keep rolling? – Yeah, I thought I’d have more time. I can like speak here
for several hours, so. (both laughing) – Well, let’s try.
– I’m fine. – Let’s hope it doesn’t come to that. (both laughing) But no, this will be fun because I haven’t seen the
React Apollo Hook stuff so this will be good to play with. So according to their docs, it sounds like we just slump out– – Yeah, you did react-apollo-hooks. – react-apollo-hooks, okay, so that– – And then you have useQuery
that you pull from there. – Okay, and then in the post itself, I’m going to import useQuery. Okay, so I still need
graphql-tag, so graphql-tag. I think I might have
already installed this. And then over here, I can
do import gql from graphql. – And the cool part of what you’re doing, react-apollo-hooks, they
added support to subscriptions I think two weeks ago so it’s really good now.
– Oh, cool! Okay, so we’ve got react-apollo-hooks and so now what I should
be able to do is in here, I should be able to say
comments equals useQuery and in here, I’m going to do– – Actually, you won’t get comments, you’ll get data error loading, so. – Ah, that’s right. Okay. So let’s set up this. That’s gonna be gql
and that’s going to be, let’s just use GraphiQL over here. I want to get– – Will be just comments. – Comments and we want the content and I think we’ll just stick
with comments here for– – It’s not only comments. It’s comments by primary key, so we need to add WHERE clause here. No, not the primary key, just comments. But we need to acknowledge–
– Oh, that’s right. – For post id. – Post id, and that post ID will be– – Equals.
– Equal to that value. Okay. – Yeah, that variable is–
– So that is gonna have to start
and we’re going to… Is it a post ID? – It’s hasura_uuid type.
– Okay. – Actually, no. It’s uuid (audio distorts), out-of-scope and that’s different now. – Uuid type, that’s right. Uuid, okay, and then that’s
going to give us the content and I’m gonna make this the ID. So then, I’m gonna do a useQuery and that is the second argument to… Is there a second
argument to get variables? – Yeah, you can, basically I think they have example over there somewhere. Yeah, it’s supposed to be
a second, yeah over here. – Got it, okay. – The same as everybody
using mutation links in second argument. – That would be post.id. Okay. – And you also need to pass suspend false because it’s like experimental thing. With query you have data
loading error, right? Experimental thing with
react-apollo-hooks, it will give you data and error and loading will be treated as folded in Suspense wrapping component. So you need to pass
suspend to false, yeah. Like that. – So I’m passing suspend false? – False, yeah.
– Or suspend true? Okay. – Yeah, ’cause it’s under
experimental section. – Got it, suspend true. Or wait, is this with– – False. – False, that’s right. – ‘Cause you need it without Suspense. – I understand, okay. Data error loading, got
it, and this should– – Yeah, you just need to check if it’s loading or if it’s error. – Okay. So I’m gonna do all that up here. Comment, or let’s see. No, how do I wanna do this? Let’s just do it as a big gross thing. So we’re going to do loading. – You can just extract it to a separate component or something. – I could do that, couldn’t I? Yeah, let’s do that. So I’m just gonna put it up here for the sake of not
getting too out-of-hand with our file system and we will do the ID is what’s gonna come into this. We’ll just pass in the post ID. So we’ll take this out, drop it in here, and the ID that we get
is going to be this one so we can put that like that. And then if loading, we will return Loading. If error, we will return the error. And otherwise, we will
return data.comments. Oops. I need this to be a thing of some sort. So we’ll do just a ul and we will return data.comments.map and that’s gonna give
us an li, needs a key, so I need to get the comment ID, and we will do comment.id here, and the comment.content inside. Come on now. All right. And then down here, I should
be able to do comments– – Yeah, that is good. – With an ID of post.id and if I have done all of this correctly, what should happen– – Supposed to work. – Let’s give it a shot. I broke it. Something broke. I didn’t start it. gatsby-develop. (laughs) Somebody else saw your spaceship. (both laughing) Okay, so now, I think, “Cannot read property
comments of undefined.” – Okay, it can’t read comments. – Because I called this data. – Yeah, ’cause you used query but the syntax is a little bit different so it’s an object destructure
and not the right structure. – Oh, aha! – That’s weird ’cause with hooks, you’re used to like
re-destructuring, right? – Okay, so we got closer
but I broke something. Unexpected variables
and variable values ID so what was my–
– I think that you passed the actual id. – So I passed in the ID, let’s log what the ID
is that I’m sending in. And what we should see
down here is the ID. – Yeah, ’cause you sent it as an object. Oh, okay, that’s good. It’s undefined.
– It’s still coming in, it’s coming in undefined. Did I in fact query for it? I did not. So that should solve
a lot of our problems. Okay, it still didn’t work. Is that because– – You’re sending an objects id. You need to restructure
it in comments component. – Oh, Jesus! Yeah, that would make sense. Whoops! Okay, unexpected variables. Okay, but it’s still an ID and now I’m logging it as an option so if I just logged in straight. – I think it’s id.id. That’s weird. Like you’re sending– – Well, so here, I could
just, I’m getting the id, logging it as an id. Oh, that’s my fault. – Oh. There we go, all right. So that’s just me being bad
at GraphQL, but. (laughs) – Now we read the subscriptions and this will be a bit challenging
but I think we’ll manage. So what we need to do, we actually need to
install a bunch of things. We need to install Apollo Link WebSockets. So apollo-link-ws.
– Apollo-link. – Apollo.link-ws. – Oh my god, link-ws. – Yeah, and we need to
install apollo-utilities. – Apollo-utilities. – And we need install, what was the name? Subscriptions-transport WebSockets. Subscriptions.
– Subscriptions. – -transport.
– Transport. – -ws. – Ws, okay. Anything else? – I think that’s it. – Okay. This is gonna be an adventure because I’ve never used any
of these three libraries. – Yeah, well, you never used subscriptions because that’s how you set up subscription base here in Apollo. – Yeah, I actually haven’t set
up a subscription with Apollo so this is a. Oh, I submitted it wrong.
– No, nice. So it will be challenged
both using it with Apollo and using it with hooks, right? – Mm-hmm. Okay, I just realized
what went wrong here. I did this like go to the abstraction. – Yeah, you wrote it twice. – GET_COMMENTS, so that’s
what I wanted was this and for some reason I just like forgot how to computer there for a second. (Jason laughs) Cool. So yeah, we’ve got, let’s
see, are we installed? Everything’s installed and I am ready. – So right now, we need
to go to our Apollo JS. – Okay. – And we need to do
actually a bunch of things. First of all, we need to… Okay, we have ApolloClient, we need ApolloLocation. Yeah, we’ll just drop the cache for now. Let’s bring WebSocket link. So it will be import websocket link. It’s a named import. No, it’s a named line. – Okay. Is there capitalization
that I need to be aware of? – Yeah, capital W, Web, capital S, Socket, capital L, Link yeah. – Okay.
– From apollo-link-ws. – Okay. – Then what we need to also bringing is import getMainDefinition
with capital M, capital D. – getMainDefinition.
– All primary. Yeah, it’s a named import also. – Okay. – From apollo-utilities. – Okay. – Now, what we need to do, we need to set up our HTTP
link and WebSocket link. Basically what we want to
do, we want to tell Apollo if our operation we are
doing is subscription, go to WebSocket link and
establish WebSocket connection and if it’s query and
mutation, just go to HTTP link. So what we’ll do, we’ll extract the thing that we have under ApolloClient and we’ll say, enter different variable, let’s say const HttpLink
equals new HttpLink at which you need to bring it up also. Yeah, we need to bring
it from apollo-link-http. – Like that? – Yeah.
– Okay. – So yeah, I think that one will do. Now, for what sort of link–
– Oh wait, that does– – Yeah, let’s do it–
– That’s not gonna work. Let’s call it that.
– Lowercase, please. – Call this one a new WebSocket. – Yeah, let’s create new WebSocketLink and we’ll pass the same URI as URI, not URL. – Aha, I feel like I did this before and I lost again 15 minutes
trying to figure out what had gone wrong. I was like, that is being smart– – But instead of https, we need to do wss ’cause we are using WebSockets
so it’s different protocol. – Come on now. All right, wss. Same headers? – Yeah, same headers. – And fetch it from–
– Now, I never used it for Gatsby actually, so I’m
not sure if I need a fetch. – I’m gonna assume that
we do just because it’s, my assumption is that we’re probably definitely gonna need that. All right, okay? – Okay. Now, we need to basically
create our splitter. Let’s create new const, call it link, and actually we need
to bring another thing. So let’s bring split from apollo-link. – Split from apollo-link. – Yeah. – I don’t know if I have apollo-link. – Okay, yeah, so we need to install it. – Apollo-link. Okay, so we’ve got split from apollo-link. – Okay, so now our link will
be basically a split function which will get another
function as first argument. This function will get, just write another named
anonymous function, just an error function. Yeah. It will get query. Distract query from that, should you? – Okay.
– Yeah. Now what we want to do, we want to do a const kind and operation, the structure from. – Kind operation.
– Kind and operation. – Whoa, operation, okay. – It’s the structure
from getMainDefinition. – getMainDefinition. – And plus query to it. So basically what we do,
we get the query and we, when you do GraphQL, you basically execute post request and you pass query and you pass string, you find query invitation subscriptions, so get my definitions utility, that gives you out of these operation, it basically extracts
what kind of operation and what operation was executed. So what we want to return, and basically the split
is like a predicate, the first punch is like a
predicate so it will return. Basically if kind equal
equal equal, just write. No, without if. Just return.
– Oh, that’s the return. – Yeah, that’s the
return kind triple equal OperationDefinition, yeah, the second one. The second one, it was
auto-completed for you. – Oh, was it?
– Yeah. I think it went and just started to… I think because you
have extra blank space, now just remove that and go back to equal. One space there and one space there. – Here?
– Yeah, this one. Okay, yeah. Operation equals subscription. – Okay, so we’re checking– – So this is which function, the first arguments, right? – If it’s an operation definition and the operation is a
subscription, then okay. – So then we pass an
argument that will basically our WebSocket link, so it will be ws. – And if not–
– And otherwise, yeah, it could be.
– Or http. – Http, yeah, that’s right. – Okay, so basically
what we’re saying here is we’re saying that
we’re creating a new link that runs this check and depending on the result of the check, either sends a WebSocket or
a regular Apollo HTTP link. – That’s right. So it’s like a splitter or
you can think about that as a, basically it’s a
compilator of sorts, right? – Sure, okay. – So you need to pass ApolloClient
and object with a link. – Like so? – Yeah.
– Okay. – And let’s see if it actually will run because I’m not sure
with only the WebSockets. If it will run, then lovely. – Gatsby develop. Okay, that’s a good sign. No, almost. Almost got there. Unable to find a native or alternative
implementation for WebSocket. So are we missing a polyfill or something? – Yeah, probably because we have, for the HTTP link, we had
fetch for our first trade and for WebSocket we need
some kind of also polyfill. – Should I see what happens
if we don’t pass this? – Yeah, yeah, try that one. – Okay, same problem. – Is it possible? We can actually check if we
are in the browser environment or if we are in yeah, in our environment. – Let’s see here. Import ws from ws. – Yeah, we’re in the same. Ah, okay. – So I need to get ws. – Yeah. Let’s install ws. – Okay. And then I’m going to do– – It’s basically the same thing we did. Instead of fetch just passed out ws. We’ll see. – paramsOrClient,
WebSocket implementation. And that’s the thing that we need to– – Oh, okay, I got what the problem is. Yeah, as a matter of fact, we need to pass that around like this and import WebSockets. – Okay, so let’s give that one more shot. Oh, come on, is that the same problem? New problem. – Are you sure we need to
pass WebSocket as it is or we need to structure that? – Great question. This says–
– No, it’s just pass it as it is. – Okay, so let’s actually look up the docs for the apollo-link-ws because I bet they tell us how to do this. – Yeah, they might. – WebSocket link. They say subscriptions-transport-ws,
so we need. Oh, I see what we did wrong. – Ah, okay, yeah. We need to use subscription. Okay, it’s different setup
actually for the client. – That’s why you read the docs. So let’s see, we’re gonna do the client and let’s see here. We’ve got our WebSocket
link so let’s do this, and this is our endpoint. – I think client won’t work ’cause we already have
these for ApolloClient. The name’s naming. – Right, client won’t
work so we’ll call this. – [Both] WebSocket client. – And then the WebSocket
link is going to be… Oh, but I still need to see– – WebSocketClient and
WebSocket implementations should be passed through
the subscription client. – Right. And I don’t know that we even need that. Let’s try without it and see what happens and then we can try again. – I think we will for all of them. Yeah, we’ll try without them. – Okay, so this, I think, options, yeah, the
options is what we want, the WebSocket implementation. Let’s try it and see what explodes. You are–
– We’ll do– – Parsing the GraphQL query in file. – Ah, okay. – Until it’s apart. What GraphQL query are
you trying to parse? – Wait, haven’t you imported
WebSockets as ws and then… Ah, okay, yeah. – Oh yep, you are absolutely
right that I doubled name that. So that is my fault. Let’s try that again. Okay. Still broken. This time, it’s broken because– – It’s in there still somewhere. You need to import that. – Oh, I understand. It is imported but I was
trying to pass it as an object but it’s actually just an argument. So we can pass that again. All right. – Hopefully. – Okay. Ooh!
– Ah, nice. – Okay, but this is interesting. ApolloBoost was initialized
with unsupported options: link. So that leads me to believe
that it’s probably– – Yeah, but it’s like a
warning from ApolloBoost. Basically, if you use subscription, you won’t use a ApolloBoost ’cause ApolloBoost is for simple setup. – Ws does not… Okay, so actually we didn’t need the ws or it’s telling us not to use the ws. So let’s try one more time. – I think we need a different
setup for null environment and for the browser environment. That’s what we– – Okay. – ‘Cause right now, it will fail on build because we need it for null environment. – Hmm, okay. All right, so–
– So what we can do, we can check if it is browser, right? We have these like– – Yes, so if we want to do
typeof window equals undefined, then we will do… Actually, we’ll just do
const WebSocket for node, then we would do ws or null, and I’m gonna call that
WebSocket for Node. And I believe if I fix my– – You have extra curly brace at the top. No? Yeah.
– Yup, here. Perfect, okay. So now what we’re doing is we’re saying if window is undefined which would signify that it is not a browser, we’re gonna use this node
WebSocket implementation, otherwise we’re gonna
pass null which I believe will trigger it to use the
the default implementation. So let’s try that again. Show me potato salad. Yeah, all right. So that didn’t explode at least. Let’s give it a shot. So this began working but we got some, it didn’t send us back the right thing. So it pulled back the whole… Hmm. – Yeah, okay. That’s weird. – Unexpected token. So it’s sending us back a page instead of giving us
the result of the query. – I think something
will, that will set up. Okay, let’s double check that. So we have WebSocket client. – GET_COMMENTS. We run this– – On theory, everything’s fine. The problem is if we go to our Apollo, we set up something wrong because it worked previously, right? – Right, and so are you sure
it’s not the link thing? – It might be.
– Like ApolloBoost? Did we fall outside of the
the ApolloBoost helper? Do we need a custom client? – Yeah, let’s bring ApolloClient
from ApolloClient actually. Yeah, I think it’s already imported. – All right, let’s see if that works without blowing up on us. You must specify link
and cache properties. – Okay, fine. We’re going to full-blown insertion. Yeah, let’s bring in memory cache. We need InMemoryCache. Cache-inmemory. – Apollo-cache-inmemory. – Yeah, this one. – Anything else? – Yeah, we try to cut the
corners and we actually cannot. (both laughing) – It’s always the dream, right? It’s just gonna work the first time. All right, so we’ve got InMemoryCache and I’m going to come back here. Where did this go? Here it is. And then you see it right there. – And you pass the cache
as yeah, like that. – Okay. And in our client, we have
cache: new InMemoryCache. – That’s right. – So now if I run gatsby-develop, it’s gonna work. I believe! All right, so we end up here. (Vladimir cheers)
We got it. (both laughing) – Oh, sorry about that. (both laughing) – You know you’re wrecking
the National Space Station up? – I guess it was a comet or something. (both laughing) – Okay, perfect. So great, so we’ve got this running, now we need to do the subscription. – Now let’s use a subscription. Now, this will be super simple. So what we need to do, just go to the components
style, the common component. – Okay. – Change query to be subscription. – Here?
– No, not here. Yeah, change query to useSubscription. – Subscriptions, and I’m
gonna have to change that– – Yeah, in all of that. Change subscription instead
of query in GraphQL syntax. Yeah, change it to subscription. – Okay. – And I believe that’s it. Okay, we have. – So I screwed up the headers somewhere because it didn’t find that
header that I was trying to pass so let’s get back into Apollo, and I was trying to pass that where? Here, and I guess I should pass it– – Yeah, you didn’t pass it. I think to WebSocketClient.
– Oh! We kept client and then this one will be– – Let’s open up the docs for a second ’cause I have dumpster memory right now. – WebSocket link, yeah. We had this up here, right? URI. – It’s an inside option so it’s supposed to be inside options. Now, options.
– Right. – Yeah, a written and true
set is supposed to be there. – Okay, so I’ve set this. I’m gonna stop and restart it. So what I did is I just moved the headers into the second option. I have a feeling this isn’t gonna work. No complaints there. What about here? Yeah, no, we’re missing something. All right, so let’s go back to the docs and to send headers. Apollo, let’ see. So the header, no, that’s not what I want at all. I want the composing links. Maybe we can just set it globally? – I think we need to
do it with middleware. Yeah, I think we need to
do it with middleware. – Awesome. – So there is set context thing so we can set context for headers. – And it’s not just getting what we said. – Let’s just try to find– – That isn’t here, is it? – It headed somewhere. It’s a little easier than
just to type everything. It’s somewhere in codes and docs, I guess. – Let’s see. – It’s enough but you can look for our apollo-link-context that’s inside. It’s there. – apollo-link-context? – Yeah.
– ApolloClient. – It’s for WebSocket
maintenance, they’re different, but just a second. – Context. Okay. – So I’m trying to find
easier set of solutions, solution actually, ’cause I don’t want us to write middleware right now. It’s possible to write, yeah, I’ll use this set context
and set handles but. – Right, and then that gets… How the hell does this get added to the… How do you actually add it to the link? – You basically do the link on
part and then pause it there. But I think I have it
already, it’s somewhere. – There’s a question from Joss DZ asking if it’s good to use
REST 2 instead of GraphQL. REST and GraphQL are tools to solve a similar but kinda different thing. REST is great if you’re
doing simple data access or if you’ve got a large
legacy REST system. – Yeah, it’s similar understanding. – So the thing about GraphQL
is that it in a lot of cases actually wraps REST and
adds extra functionality on top of it. GraphQL is kind of like an evolution for anybody who’s
watching who’s old enough to remember things like SOAP,
it’s kinda the same thing. SOAP was a great way to get
data and then REST was invented and it was kind of a more usable way of getting data comparatively because SOAP had a lot of
ceremony and requirements, and then GraphQL just kinda
takes this complexity of REST which was that you had
to make a lot of requests to a lot of different databases and then collate that data somehow. GraphQL just does the collation for you so that you get those relationships. So yeah, I think, ultimately, it’s fine if you wanna use REST. It’s not gonna be the end of the world. It’s not a mark of shame or anything, it’s just GraphQL solve a
couple problems more elegantly. (Jason laughs) Yeah, we got a SOAP with
a vomit emoji in the chat which a couple of my very
early projects were using SOAP and I remember being
just completely befuddled by the whole process. Were you able to find the
one for different settings? – Yeah, I think so. Just a second. I’m close. I think it’s over here. – Let’s see. Oops! Forgot to disable all my notifications. – Just a second. Okay, I figured this out. Yeah, we forgetting the one key. So it’s like we have clean options, we have reconnectors through,
and then we pass headers. Instead of headers, we need
to pass connectionParams. – connectionParams. – Yeah and it will be a function, that will be a function
that will return an object that will have headers. – Got it. So we can just do this and then I’ll take my
headers back out of here and put it in here. Okay. So let’s give that a shot. We’ll stop and start. – If it won’t work, then
we’ll do middleware. – Okay. There we go. All right, so now, we’ve
got this post running. – So the values including. – Let’s add something special. So we’re gonna do here, I’m gonna split this
out and make it smaller. All right. So now we’ve got here, I’m going to do mutation
to insert a comment and the thing that I forgot to post is– – I think you already did that so you can’t click on
history and you will save it. – Insert_comments. Make sure the post ID lines up, okay, and let’s do another comment
and let’s just run it. There we go! – Yeah! – Let’s run it again. Oh my goodness!
– Ooh! – So that’s pretty slick. Obviously, we hit a couple snags that are trying to get the
the WebSocket stuff set up but knowing that this is possible and ultimately, it’s 50 lines of code to get this whole WebSocket thing going. It’s a little– – It was a challenge for both of us ’cause I had never used
WebSockets with Gatsby, you never used WebSocket
with subscriptions so yeah. – Yeah, this is slick. Okay, so I think this is
probably a good place to call it before we dig ourselves another hole. – That’s right. – What we should do is
let’s sync after this and figure out how to secure that token so that we can release this code. – Yeah. I think what we can do actually, we can schedule this at some point, we can do other stream with more in-depth authentication
and business logic. – Okay. – Maybe continue from where we ended, just editing, I don’t know, filtering bed-wolds filter
using serverless functions and authorization with I don’t know, Cognito for example and yeah.
– Okay. For the immediate future, let’s just make sure that
we can ship something that we can use that has the
authentication place and– – I mean for the upcoming months or so. – Yeah. But in the meantime, people
can follow you on Twitter. You are Vladimir Novick. – Yeah, that’s me. – Anything else that we should check out? – That’s my cool avatar from
React customer last year. – This is a really cool avatar. That was very cool of them to do that. Awesome! Anything else that people should check out or know before we wrap up? – Yeah. Well, the website, Hasura.io, just go there to check it out. We showed how to run from Heroku but as you can see, you
can run in it Docker, on the DigitalOcean, and Azure,
AWS, Google Cloud Platform, basically anything that you– – That was a pop quiz to see if you knew all the logos. (laughs) – Yeah. (both laughing) Yeah, basically anywhere
where you can run Docker, you can run the engine. It’s not limited to creating from scratch so what you can actually do, it’s pretty easy to just get
into docs, getting started. When you click on Get Started with Docker, for example click on that for a second. – Okay. – So you have two versions you
can run with Docker Compose and then you will have both
Postgres and Docker Container locally on your machine but sometimes you want to connect to external database or something then. Everything is described here
in the docs how to do that. For that, if you have questions, there is Hasura Discord Channel. On the homepage, there is a link. So feel free to get
there and ask questions. You can click on Join Discord. I also run a radio, a
podcast, 3factorRadio, and actually we just
released the episodes. So when we’ll finish stream, I will tweet about the fact that I’ll release episode
with you, Jason, so. – Oh, cool! Very cool.
– The one we recorded. – Yeah, that was a lot of fun. – Yeah, I’m so excited.
– Well great, so yeah, definitely go check
out this Community tab. Go join the Discord,
follow that 3factorRadio, that was a lot of fun to do, and yeah please give Hasura a try. That was a lot of fun. We’ll post the code a little bit later once we work out that token issue so that people aren’t
posting high-powered tokens in their demos. But yeah, so that’ll come
up a little bit later but otherwise, thank you so
much for joining us tonight, or this morning. God, what timezone am I operating in? – It’s eight p.m. for me and you’re– – Oh, all right, so I’m in your timezone. Cool. Thank you very much, everybody. And we will see you next time. Next up on the stream, we are going to do a Auth0
deep-dive with Ado Kukic, I think, is how you say that name, and I really apologize if it’s not. He’s coming over from Auth0 to teach us how to do
authentication in Gatsby apps. So thanks again and we
will see you next time. – Yeah, thank you, everybody.

2 thoughts on Create a realtime web app with Hasura and Gatsby — Learn With Jason

  1. part at around 1:18:00, where you were talking about what you are leaving out for the sake of time was a bit fast.
    What exactly did you leave out, that you would include in production code, or to phrase it differently what should you do differently than you did when writing production code (except for checkingfor an error object obviously)?

Leave a Reply

Your email address will not be published. Required fields are marked *