Skip to content

Create a Gallery with Remote Images

Gatsby, an open-source tool for building high-performance JAMstack apps, boasts numerous plugins that extend its capabilities. For example, by leveraging Gatsby’s source plugins, we can source data from multiple services, APIs, and even Excel spreadsheets.

Cloudinary is a cloud-based, end-to-end media-management platform on which you can store, dynamically optimize, and responsively deliver images and videos for both desktop or mobile apps.

The Gatsby-Source-Cloudinary plugin fetches optimized media assets from a folder on Cloudinary in a Gatsby project. Additionally:

  • You can declaratively query Cloudinary’s media assets alongside other application data with GraphQL.
  • Cloudinary delivers media assets through a content delivery network (CDN), reducing the app- bundle size on app build.
  • Gatsby-Source-Cloudinary automatically optimizes the quality and format of the media files delivered by Cloudinary.

Thus, you have the best of two worlds: high-performance apps along with optimized delivery of media assets.

This tutorial takes you through building a responsive image gallery with Gatsby and images from Cloudinary. Because Gatsby is written in React.js, you must have a working knowledge of JavaScript and React.js.

We completed this project in Codesandbox. You can fork it to run the project. To run the project, you need to specify your Cloudinary account API Key, Secret, and cloud name. You can do this using a .env file in the project’s root directory, or add the credentials directly in Codesandbox using the “Server control panel” menu option on the left.

See the .env.example file in the project’s root – a template for creating environment variables.

https://codesandbox.io/s/gallery-images-in-gatsbyjs-using-gatsby-source-cloudinary-tnc1l?file=/gatsby-config.js

We need Node.js, and its package manager, npm, for this project. To check if we have them installed on our system, we run the following command:

    node -v && npm -v

If the output shows no version numbers, go to Nodejs.org to download and install Node.js, which ships with npm.

Next, we install the Gatsby.js CLI using the terminal command.

    npm install -g gatsby-cli

To source images from Cloudinary, we must first set up an account there. Cloudinary offers a generous, free tier account that’s largely adequate for starter projects, and scales with the project.

Afterward, we do the following:

  1. Upload the images for the image gallery to a folder in our media library on Cloudinary. We give the folder a name of our choice, e.g., gallery.
  2. We obtain our API key and API secret from the Cloudinary dashboard.

Gatsby.js ships starters used to generate new projects with a base setup quickly. To create a new Gatsby.js project in a folder of our choice with the default starter, we use this command:

    gatsby new cloudinary-site
Code language: JavaScript (javascript)

Next, we navigate to the project directory and start a new development server on http://localhost:8000 with this command:

    cd cloudinary-site && gatsby develop

Because it contains GraphQL, Gatsby simultaneously creates a GraphQL IDE on http://localhost:8000/___graphql, with which we’ll build GraphQL queries later.

Now, we go to http://localhost:8000 to see the new Gatsby project, which looks something like this:

We need two other packages for this project:

We install them with NPM, using the command:

    npm i --save dotenv gatsby-source-cloudinary

We configure all plugins, including those that accompany the default starter, in the gatsby-config.js file, which resides in the root directory of Gatsby projects. We do the following:

We import the dotenv module we installed earlier to the gatsby-config.js file, and configured the gatsby-source-cloudinary plugin with this code:

    require('dotenv').config();
    
    module.exports = {
      ...
      plugins:[
      ...
      {
          resolve: `gatsby-source-cloudinary`,
          options: {
            cloudName: process.env.CLOUDINARY_CLOUD_NAME,
            apiKey: process.env.CLOUDINARY_API_KEY,
            apiSecret: process.env.CLOUDINARY_API_SECRET,
            resourceType: `image`,
            prefix: `gatsby-source-cloudinary/` 
          }
        }
      ]
    } 
Code language: JavaScript (javascript)

The gatsby-source-cloudinary plugin takes these options:

  • cloudName, apiKey, and apiSecret: These are credentials from our Cloudinary console, stored as three separate environment variables for security.
  • resourceType: This is the media assets’ resource type: either an image or a video.
  • prefix: This is the folder (in our Cloudinary account) in which the files reside. In the example above, I named this folder gatsby-source-cloudinary . Assign a name of your choice.

Other options are type, tags, and maxResult.

In the root directory of our project, we create a .env file to hold our Cloudinary credentials.

    CLOUDINARY_API_KEY=xxxxxxxxxxxxxx
    CLOUDINARY_API_SECRET=xxxxxxxxxxxxxxxxxxxx
    CLOUDINARY_CLOUD_NAME=xxxxx

The dotenv package exposes those environment variables in the project.

We restart the Gatsby development server to see the plugin in action, as in this example:

Note the info log, which displays the CloudinaryMedia nodes. Those images are ready to be queried in Gatsby components.

In the src/components folder, we create a component file called ImageGallery.js and add the React functional component to the file to create the image gallery.

First, we import all required dependencies and then query all the Cloudinary images sourced into the CloudinaryMedia nodes with the useStaticQuery hook.

    import React from 'react'
    import './gallery.css'
    import {useStaticQuery, graphql} from 'gatsby'
    const ImageGallery = () => {
      const data = useStaticQuery(graphql`query CloudinaryImage {
            allCloudinaryMedia {
              edges {
                node {
                  secure_url
                }
              }
            }
          }`
        )
      return(...)
        const clImages = data.allCloudinaryMedia.edges
      export default ImageGallery
Code language: JavaScript (javascript)

Following this, we loop through those image URLs to create a gallery with the component.

    const ImageGallery = () => {
      // data fetching goes in here
    
      return (
            <div>
              <div className="image-grid">
                {clImages.map((image, index) => (
                      <div className="image-item" key={`${index}-cl`}>
                        <img src={image.node.secure_url} alt={"no alt :("} />
                      </div>
                    ))
                }
              </div>
            </div>
          )
      }
    export default ImageGallery
Code language: JavaScript (javascript)

To style the grid gallery component, we create a file called ./gallery.css in src/components . We add the CSS styles to the file, as follows:

    .image-grid {
        display: grid;
        grid-gap: 10px;
        grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
        grid-auto-rows: minmax(50px, auto);
      }
      .image-grid .image-item:nth-child(5n) {
        grid-column-end: span 2;
      }
      .image-grid img {
        display: flex;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
Code language: CSS (css)

The above styling renders your image gallery into a beautiful, responsive masonry grid.

We replace the existing content of the index.js file in the src/pages folder with the newly created ImageGallery component.

    import React from "react"
    import Layout from "../components/layout"
    import SEO from "../components/seo"
    import ImageGallery from "../components/ImageGallery"
    const IndexPage = () => (
      <Layout>
        <SEO title="Home" />
        <h1>Image Gallery</h1>
        <p>Here's a Gatsby site with optimized images in a masonry grid, served from <a href="https:cloudinary.com" target="_blank" rel="noopener noreferrer">Cloudinary</a></p>
        <div style={{ marginBottom: `1.45rem` }}>
          <ImageGallery/>
        </div>
      </Layout>
    )
    export default IndexPage
Code language: JavaScript (javascript)

Gatsby automatically creates dynamic routes for single pages in the src/pages folder, with index.js being the root or home page.

Optional:. Feel like tweaking the styles a bit? In the src/components/header.js file, change the background style property of the <header> element to #002954.

We rewrote the site title, pulled from the site metadata (the title property) specified in gatsby-config.js to “Gatsby-Cloudinary Image Gallery”.

We restart the development server and have a look at the updated page. Here’s an example:

To create a deployable, optimized build, we run the following terminal command:

    gatsby build

In this post, we learned how to leverage the performance benefits of Gatsby.js’s build process to deliver remote images stored on Cloudinary. We built an image gallery with photos from Cloudinary.

You can check out the Gatsby-Transformer-Cloudinary plugin, with which you can upload media assets to Cloudinary and handle Cloudinary transformations right in the GraphQL queries.

You may find these links useful:

Back to top

Featured Post