Hello everyone!
Let's do a project similar to: https://momazos.netlify.app/
It's basically a list of images stored on Airtable 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:
$ npx gatsby new momazos
this creates a folder structure based on the Gatsby Starter Default, 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
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)
π You can see it here
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
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:
{
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])
}
}
}
}
}
}
}
}
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
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
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
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
now create a file in src/components/List.jsx
this component is responsible for rendering the name and image.
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
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.
Top comments (1)
Amazing Panda!!!!