Image Gallery with Gatsby, Netlify and Airtable.
Tags: react, gatsby, graphql, netlify
Published: 2021-06-21 17:43:20

Hello everyone! 

Let's do a project similar to: https://momazos.netlify.app/

It's basically a list of images stored on [Airtable](https://airtable.com/) and consumed by Gatsby through a source plugin called `gatsby-source-airtable`.

For the "UI design" we will use chakra-ui, which has several default components.

> as of the date I published this post Gatsby is in version 3

## Start the project

We're going to start the project with the following command:

```bash
$ npx gatsby new momazos
```

this creates a folder structure based on the [Gatsby Starter Default](https://github.com/gatsbyjs/gatsby-starter-default.git), At this point you should have a folder structure similar to this:
 
```
- .gitignore
- .prettierignore
- .prettierrc
- LICENSE
- README.md
- gatsby-browser.js
- gatsby-config.js
- gatsby-node.js
- gatsby-ssr.js
- node_modules
- package-lock.json
- package.json
- src
  - pages
    - index.js
```

✨ now run in the terminal the following command:

```
 $ npm start
```
and you should see the development server at https://localhost:8000

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/umei87kq076iccxuvkyt.png)


## Airtable table structure

for this case we have the following structure:

- Name (name of image)
- Attachments (field with image )
- Tags - (image related tags)
- Status - (Active / Inactive)
- Created - (creation date)
- Last Modified Time (edition date)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2r9fiajj2x60qj47xpr.png)

👀 [You can see it here](https://airtable.com/invite/l?inviteId=invfytv6NZm0ZRRVQ&inviteToken=12705bff0449aecc76e76c8091a4b67df6b64c55184da53a1ca5030a69e3770a&utm_source=email)
  
## Install Gatsby Airtable Source plugin

now we're going to install the Airtable plugin by running the following command:

```
$ npm install gatsby-source-airtable
```

to configure it in Gatsby we need modify the `gatsby-config.js`

```javascript
plugins: [
  {
    resolve: `gatsby-source-airtable`,
    options: {
      apiKey: `I-C-WIENER-405-XXX-XXX-XXX`, 
      tables: [
        {
          baseId: `YOUR_AIRTABLE_BASE_ID`,
          tableName: `Memes`,
          mapping: { Attachments: `fileNode` },
         },
      ]
    }
  }
];
```

> you can get an apiKey at https://airtable.com/api

In my case "Memes" is the name of the database and the mapping is the way a file type is related in Gatsby.

## Interacting with the data 

at this point, you have access to the airtable data and you can run queries to the graphql schema.

Now when I start the development server, Gatsby will store the data to be able to make graphql queries at the URL https://localhost:8000/__graphql

📋 We're going to copy the following query: 

```graphql
{
  allAirtable(
    filter: {table: {eq: "Memes"}, data: {Status: {eq: "Active"}}}
    sort: {fields: data___Created, order: DESC}
  ) {
    edges {
      node {
        id
        data {
          Name
          Attachments {
            localFiles {
              childImageSharp {
                gatsbyImageData(layout: FULL_WIDTH, formats: [AUTO, AVIF, WEBP])
              }
            }
          }
        }
      }
    }
  }
}
```

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/95j6nlfm5u3o6f8avq6a.png)

As you can see, we have access to all the data available in our Gatsby project.



## Install chakra-ui 💅🏼

To use Chakra UI in your Gatsby site, you need to install the plugin and its peer dependencies

```bash
npm i @chakra-ui/gatsby-plugin @chakra-ui/react @emotion/react @emotion/styled framer-motion
```

- 1 Add `@chakra-ui/gatsby-plugin` to gatsby-config.js

```js
plugins: [
  {
    resolve: `gatsby-source-airtable`,
    options: {
      apiKey: `I-C-WIENER-405-XXX-XXX-XXX`, 
      tables: [
        {
          baseId: `YOUR_AIRTABLE_BASE_ID`,
          tableName: `Memes`,
          mapping: { Attachments: `fileNode` },
         },
      ]
    }
  },
`@chakra-ui/gatsby-plugin`
];

```

- 2 configure the chakra provider in the file `gatsby-browser.js`

```jsx

const React = require("react");
const ChakraProvider = require("@chakra-ui/react").ChakraProvider;
const extendTheme = require("@chakra-ui/react").extendTheme;

const config = {
  useSystemColorMode: true,
};

const theme = extendTheme({ config });


exports.wrapRootElement = ({ element }) => {
  return (
    <ChakraProvider resetCss theme={theme}>
      {element}
    </ChakraProvider>
  );
};

```

> you can check the chakra-UI documentation, it is very clear and intuitive, similar to that of tailwindcss.

📚 [Docs](https://chakra-ui.com/docs/getting-started)

now create a file in `src/components/List.jsx` this component is responsible for rendering the name and image.

```jsx
import React from "react";
import { GatsbyImage } from "gatsby-plugin-image";
import { Box, AspectRatio, Badge, useColorModeValue } from "@chakra-ui/react";

function Item({ node, loading }) {
  const bg = useColorModeValue("white", "gray.900");
  const [file] = node.data.Attachments.localFiles;
  return (
    <Box
      borderWidth="1px"
      borderRadius="lg"
      overflow="hidden"
      key={node.id}
      position="relative"
      bg={bg}
    >
      <AspectRatio maxW="620px" ratio={4 / 3}>
        <GatsbyImage
          loading={loading}
          image={
            file.childImageSharp.gatsbyImageData
          }
          alt={node.data.Name}
        />
      </AspectRatio>

      <Box py={2} px={2}>
        <Box d="flex" alignItems="baseline">
          {node?.data?.tags?.map((tag) => {
            return (
              <Badge id={tag} borderRadius="full" px="2" colorScheme="facebook">
                {tag}
              </Badge>
            );
          })}
        </Box>
        <Box
          mt="1"
          fontWeight="semibold"
          as="h3"
          lineHeight="tight"
          isTruncated
          px={1}
        >
          {node.data.Name}
        </Box>
      </Box>
    </Box>
  );
}

export default React.memo(Item);
```



With all this, now you just have to join everything on the Home page.

`src/pages/index.jsx`

```jsx
import React from "react"
import List from "../components/List";
import { Container, Grid } from "@chakra-ui/react";
import { graphql } from "gatsby"

const IndexPage = ({ data }) => {
   return (
       <Container maxW="container.xl"> 
         <Box px={4} mt={4}>
          <Grid
            templateColumns={{
              base: `repeat(1, 1fr)`,
              sm: `repeat(3, 1fr)`,
              xl: `repeat(4, 1fr)`,
            }}
            gap={{
              base: 4,
              xl: 6,
            }}
          >
          {data.allAirtable.edges.map(({ node }, index) => {
              const loading = index <= 4 ? "eager" : "lazy";
              return <List node={node} loading={loading} />;
            })}
          </Grid>
       </Container>
)
}

export const query = graphql`
  {
    allAirtable(
      filter: {table: {eq: "Memes"}, data: {Status: {eq: "Active"}}}
      sort: {fields: data___Created, order: DESC}
    ) {
      edges {
        node {
          id
          data {
            Name
            Attachments {
              localFiles {
                childImageSharp {
                  gatsbyImageData(layout: FULL_WIDTH, formats: [AUTO, AVIF, WEBP])
                }
              }
            }
          }
        }
      }
    }
  }
`

export default Index

```

✨ Thanks for reading, if you have any questions feel free to DM me on Twitter.

<a href="https://www.buymeacoffee.com/devrchancay" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>