Create a real time web app with Hasura and Gatsby
Tags: gatsby, hasura, graphql
Published: 2019-04-21 15:59:51

---
title: Create a real time web app with Hasura and Gatsby
published: true
description: Live streaming creating Blog with real time subscriptions using Gatsby and Hasura
tags: Gatsby, Hasura, GraphQL
---

A bit more than a month ago we live streamed how to create Gatsby blog with Hasura. This blog post summarizes it. If you haven't watched this video as well as other videos we have on [Hasura Youtube channel]() I strongly suggest to check it out

{%youtube HTEGGndT3zY%}

# What we were creating. 
The idea was to create a simple blog powered by GraphQL backend. For backend we chose [Hasura](hasura.io) because lots of reasons I layed out in this blog post:

{%twitter 1092751461824585728%}

We started by deploying Hasura to Heroku and creating bunch of tables, connecting them with foreign keys and immediately we had queries subscriptions and mutations generated for us by Hasura. We had some weird behaviors though. Columns were dropping, fields were changing. It was kinda weird at first and then we realized that there were people trolling with us. Because endpoint was not secured and console was enabled, people were able to connect to it and change schema. 

When we realized that we secured an endpoint by using `HASURA_GRAPHQL_ADMIN_SECRET` environment variable which we tried to keep secret from our audience. Finally everything was stable and people just could not troll us. 

# Creating gatsby site

We created our gatsby site by running 
`gatsby new . gatsbyjs/gatsby-starter-hello-world`

to get very basic setup.

# Integrating Hasura GraphQL into Gastby

We installed [gatsby-source-graphql](https://gatsbyjs.org/packages/gatsby-source-graphql) and configured it to work with `HASURA_GRAPHQL_ADMIN_SECRET`, but in real world scenario we will have Authorization bearer token, so our gatsby.config will look like this:


```javascript
const fetch = require("isomorphic-fetch")
const createHttpLink = require("apollo-link-http")


/// Rest of the code

{
  resolve: "gatsby-source-graphql",
  options: {
    typeName: "hasura",
    fieldName: "blog",
    // Create Apollo Link manually. Can return a Promise.
    createLink: () => {
     return createHttpLink({
       uri: 'hasura graphql endpoint',
         headers: {
           'Authorization': `bearer ${token}`,
         },
         fetch,
    })
  },
}

```

To read more about Authentication you can read it in my blog post ["Hasura Authentication Explained](https://dev.to/hasurahq/hasura-authentication-explained-2c95)

In our live stream we used our admin secret just for simplicity.

> Note: You cannot use admin secret in production environment cause your client will be able to do any changes to database


So at that point we were able to query our `blog` field

# Creating pages 

We started creating our pages by exporting our query and referencing the data from blog field. Basically under `blog` field we had all queries that we can run with Hasura engine.


{% gist https://gist.github.com/vnovick/05a19dda99ddd96e31c03de43c9e2aed %}


Once we had our first page with a list of blog posts, Jason started creating other pages by using Gatsby [createPages api](https://www.gatsbyjs.org/docs/node-apis/)

In order to create these pages programmatically what had to be done is the following: 
After getting result from Hasura `posts` graphql query, create each page programmatically with `path/${post.id}` path. In that way we were able to link to these pages later on. For `post` page component we created a new `template/post.js` file. There we added real time functionality later on.

{% gist https://gist.github.com/vnovick/ad03d45b08ee62112314862f08231898 %}


# Adding GraphQL subscriptions

That was a tricky part. Gatsby queries Hasura GraphQL endpoint on build, but we had to add some real time capabilities using subscriptions, so we needed our post page to behave like a single page app of sorts. 

So we had to set up Apollo with `ApolloProvider` and subscriptions. If you've dealt with `react-apollo` in the past you probably know that you need to create two links and create a new instance of `ApolloClient` you can read more about it [here](https://www.apollographql.com/docs/react/advanced/subscriptions#subscriptions-client):


With Gatsby it's similar, but a bit different. We had to create a root element wrapper and specify it in both `gatsby-browser.js` and `gatsby-ssr.js` so Gatsby will get it rendered both when doing server side rendering and both when rendering on the client. This element looked like this.

```react
export const wrapRootElement = ({ element }) => (
  <ApolloProvider client={client}>{element}</ApolloProvider>
)
```

# Dealing with SSR and subscriptions

Defining HttpLink on the client is easy, but when SSR is involved you need to pass fetch implementation to HttpLink, so it won't fail. 

```javascript
import fetch from "isomorphic-fetch"

//rest of the code

const http = new HttpLink({
  uri: "https://hasura-gatsby-livestream.herokuapp.com/v1alpha1/graphql",
  fetch,
})
```

With subscriptions it was similar, but instead of passing `fetch` we had to use a package `ws` and do a custom check if we are running in the browser or not:

```javascript
//...
import ws from "ws"
//...

const wsForNode = typeof window === "undefined" ? ws : null

//...

const wsClient = new SubscriptionClient(
  "wss://hasura-gatsby-livestream.herokuapp.com/v1alpha1/graphql",
  {
    reconnect: true
  },
  wsForNode
)

//...
const websocket = new WebSocketLink(wsClient)

```

After configuring our apollo in that way we were able to subscribe to changes from our `post` template by using 

```javascript
useSubscription(SUBSCRIPTION_NAME, { suspend: false }, variables: { id })
```

Yeah we used React hooks.

# Summary 

So what is the purpose of this blog post. First of all a recap on something cool we did a bit more than a month ago, second remind that Gatsby can be used with real time data and that Hasura will give you GraphQL API on top of your existing or new Postgres in no time and also to remind that live coding with other folks in the community is one of my top priorities so if you have something you wanna live code together involving Hasura and some other awesome tool, feel free to reach out to me on twitter. My [Twitter DMs](http://twitter.com/VladimirNovick) are open. 

And subscribe to our [Youtube channel](https://www.youtube.com/channel/UCZo1ciR8pZvdD3Wxp9aSNhQ) or [Join Discord](https://discord.gg/hasura)