JAMStack Fun: Combining StackBit, Forestry, Netlify, Gatsby, Hasura, Glitch
Tags: javascript, gatsby, graphql, 100daysofcode
Published: 2020-04-22 08:21:06

For days 6-7 of #100DaysOfCode, I did various [JAMStack](https://www.netlify.com/products/forms/) experiments with SaaS and open-source tools, putting them together to see what would happen.

## Trying Out Stackbit

I signed up for a [Stackbit](https://www.stackbit.com/) account and used their site builder to create a project:
* Theme: Azimuth
* Site generator: [Gatsby](https://www.gatsbyjs.org/)
* CMS: [Forestry](https://forestry.io/) (Always wanted to try it!)
* Deployment: GitHub repository with Netlify build + deploy (the only current options available. I look forward to Gitlab coming soon!)

I connected my Forestry and GitHub accounts.

Stackbit says it deployed my site. Ooh, it's really live:

![My deployed Stackbit static site](https://dev-to-uploads.s3.amazonaws.com/i/afdfa3ahstpi4s0ift3o.png)

I clicked *Claim* to claim the Netlify project. It worked, yay.

Then I clicked *Edit in Forestry* to edit the content.

## Trying Out Forestry

Forestry provides a GUI for editing Gatsby content. It also supports Hugo, Gridsome, Jekyll, and other static site generators.

It's pretty cool, and I could see it being useful for people who can't build their static site locally or are editing from a mobile device.

The lag between updating a site via Forestry and seeing the new deployed version on Netlify was a few minutes. For my purposes, I find running `npm run develop` easier because I can see the static site changes on localhost in seconds.

## Adding a Netlify Function

Next I added a [Netlify function](https://www.netlify.com/products/functions/). Initially it'll do almost nothing, but I could see it implementing something dynamic and server-side like what you would expect of an Express or Django web application.

I cloned the GitHub repo, then created a Netlify function by copying [functions/hello.js](https://kentcdodds.com/blog/super-simple-start-to-serverless) by @kentcdodds into my project. I added it to my build in *netlify.toml*. Then I git committed and then went to Netlify to watch the build go.

Now that the function's deployed, it's here:
https://curious-rosemary-e8299.netlify.app/.netlify/functions/hello?name=Uma

Whatever you pass into `name` gets shown on the page by the function:

```js
// functions/hello.js from https://kentcdodds.com/blog/super-simple-start-to-serverless
exports.handler = async event => {
    const subject = event.queryStringParameters.name || 'World'
    return {
      statusCode: 200,
      body: `Hello ${subject}!`,
    }
  }
```

I'd like to expand this into something real and maybe have it get triggered by a form submission via a [Netlify form](https://www.netlify.com/products/forms/) like the `contactForm` provided by the sample code. But in the interest of time, I'm saving that for another day to focus on getting the Gatsby site to display dynamic remote API data.

## Experimenting with Gatsby

It's been years since I last used React, so getting Gatsby to do what I wanted was a challenge. My hope at this point was to replicate what a Django `ListView` does in JAMstack.

I created an `items.js` page to play in:

```jsx
import React from "react"
export default ({ data }) => (
    <div>
        Hello!
    </div>
)
```

Next, I looked into populating the page with dynamic data. If I could grab data onto this static page from a remote GraphQL endpoint, that would be great.

Gatsby uses GraphQL, so I started with using that as test data:

```jsx
import React from "react"
export default ({ data }) => (
    <div>
        <h1>Items List {data.site.siteMetadata.title}</h1>
        <p>This is a static site, but it's loading items dynamically from GraphQL:</p>
        <ul>
          {data.site.siteMetadata.header.nav_links.map(x=> <li>{x.label}</li>)}
        </ul>
    </div>
)

export const query = graphql`
  query {
    site {
      siteMetadata {
        header {
          nav_links {
            label
          }
        }
      }
    }
  }
`
```

## Setting Up a GraphQL API with Hasura

[Hasura](https://hasura.io/) is an open-source, Heroku-deployable tool that can take existing databases and give you a GraphQL API. 

I did the first part of the Hasura tutorial and loved it. Now I have a *todos* table I can query:

```gql
query MyQuery {
  todos {
    id
    title
  }
}

```

The response from Hasura with my sample data:

```graphql
{
  "data": {
    "todos": [
      {
        "id": 1,
        "title": "My First Todo"
      },
      {
        "id": 2,
        "title": "Second Todo"
      }
    ]
  }
}
```

## Adding a New Gatsby GraphQL Root

I did an `npm install gatsby-source-graphql` then added my Hasura GraphQL API to *gatsby-config.js*:

I see that the [example from the Gatsby docs](https://www.gatsbyjs.org/docs/third-party-graphql/#basic-example) points at https://api.graphcms.com/simple/v1/swapi which is down. 

Looks like that site, [GraphCMS](https://graphcms.com/), was featured on ProductHunt today...I'll sign up and see if they have an updated sample endpoint. Hmm, it looks like an interesting rabbit hole for another day.

In Hasura, I went to `Remote Schemas > *Try it with Glitch*` and found [hasura-sample-remote-schema.glitch.me/ ](https://hasura-sample-remote-schema.glitch.me)

With @danielfeldroy's help we added the new root to *gatsby-config.js*:

```json
        {
            resolve: "gatsby-source-graphql",
            options: {
              // This type will contain remote schema Query type
              typeName: "query",
              // This is the field under which it's accessible
              fieldName: "hasuraSample",
              // URL to query from
              url: "https://hasura-sample-remote-schema.glitch.me/",
            },
          },
```

Then he figured out this query worked in Glitch:

```gql
query {
  hello 
}
```

In http://127.0.0.1:8000/___graphql we got this query to work:

```gql
query {hasuraSample {
  hello
}}
```

## Showing Remote GraphQL Data on a Gatsby Page

Finally, I updated *items.js* to be:

```jsx
import React from "react"
export default ({ data }) => (
    <div>
        <h1>Items List</h1>
        <p>This is a static site, but it's loading items dynamically from GraphQL:</p>
        <ul>
          {data.hasuraSample.hello}
        </ul>
    </div>
)

export const query = graphql`
  query {hasuraSample {
    hello
  }}
`
```

With that, http://localhost:8000/items now shows a static Gatsby page with the live data from the Glitch-hosted Hasura Sample Remote Schema!

![JAMstack: Putting It All Together](https://dev-to-uploads.s3.amazonaws.com/i/wky9toai3mqr5vpjhl8j.jpg)

It was really fun to play around and put all these JAMstack toys together, particularly the ones that auto-configured themselves and auto-deployed. Every piece served a purpose and did it well. That was cool!