We're live-coding on Twitch! Join us!
Serving Remote Optimized Images w/ gatsby-image w/o GraphQL

Serving Remote Optimized Images w/ gatsby-image w/o GraphQL

Part 1 of this series chronicles the process of using remote images from Cloudinary in GatsbyJS projects through GraphQL queries. Here in part 2, you’ll learn how to —

  • Leverage remote images stored in Cloudinary and served through an optimized content delivery network (CDN).
  • Serve fluid or fixed images with gatsby-image.
  • Render images for responsiveness and optimize them with gatsby-image.
  • Transform those images with Cloudinary.

For instance, we can quickly change this penguin image:

Specifically, this part guides you through two processes:

  1. Fetch an image from Cloudinary with the getFluidImageObject API of gatsby-transformer-cloudinary and render that image with gatsby-image. You can fetch any image from your Cloudinary account. Also, even after applying the Cloudinary transformations that you specify, the API can still optimize that image with gatsby-image during the build process.

    This image-fetching process requires no GraphQL queries.

2. Create a user interface and typography with Chakra UI.

Preliminary Steps

Before you start, you must have installed Gatsby.js with npm on your system. See the Installation section in Part 1 for details.

Also, create a new GatsbyJS project with the default GatsbyJS starter. Type:

gatsby new gtc-demo-2

Alternatively, clone this branch of the project described in part 1.

Setup of Project Configurations

If you haven’t done it yet, follow the steps in the three subsections under Setup of Project Configurations in Part 1 to—

  1. Create a Cloudinary account.
  2. Set up gatsby-config.js.
  3. Add environment variables.

Design of Page Layout

You’re now ready to create a webpage and its layout.

First, start a development environment by typing this command:

gatsby develop

Afterward, copy over the files in the components and pages directories of the project in part 1.

Image Fetching With getFluidImageObject and getFixedImageObject APIs

Even though both getfluidImageObject and getFixedImageObject fetch images from Cloudinary accounts with multiple or chained transformations, the two APIs vary as follows:

getFluidImageObject returns fluid images with the breakpoints that you specified and, if you did not specify any, it returns breakpoints with the maximum width of 650.

getFixedImageObject returns fixed-width images, passing them from the asynchronous calls of the functions to the fluid or fixed property of the gatsby-image <Image/> component.

Both APIs fetch images with a single asynchronous operation, hence no need for GraphQL queries.

Creation of a Webpage That Contains a Single Image

Now create a webpage that contains an image fetched with getFluidImageObject. Apply the same layout from part 1.

By default, gatsby-transformer-cloudinary optimizes the quality and format of images through the f_auto and q_auto Cloudinary transformation parameters.

GatsbyJS builds pages from the JavaScript (JS) files in the src/pages directory.

Do the following:

  1. Create a JS file titled single.js in src/pages. GatsbyJS adds single.js to the route /single.

  2. Import the required modules into single.js with this code:

import React, { useEffect, useState } from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { getFluidImageObject } from "gatsby-transformer-cloudinary"
import Image from "gatsby-image"
import { Box, Heading, Text } from "@chakra-ui/core/dist";

3. Create and export a functional component titled SinglePage. In the function, fetch a single Cloudinary image with a public ID of your choice. Below is the code, in which the public ID is gatsby-source-cloudinary/penguin:

const SinglePage = () => {
    const [fluid, setFluid] = useState(false);

    useEffect(() => {
        async function getData() {
            const res = await getFluidImageObject({
                public_id: "gatsby-source-cloudinary/penguin",
                cloudName: 'chuloo',
                originalHeight: 400,
                originalWidth: 500,
                transformations: ["e_replace_color:purple", "a_hflip"],


    }, []);

    return (
            <SEO title={"single"}/>
                <Heading as={'h1'} size={'lg'} m={5} textAlign={'center'}>Single Fluid Image</Heading>
                <Box maxWidth={[350, 400, 500]} mx={"auto"} shadow="md" borderWidth="1px" rounded={'lg'} p={3}>
                    {fluid ? <Image fluid={fluid}/> : "loading..."}
                <Box my={30}>
                    <Text>This is a single image sourced directly from Cloudinary. This image can be any image in your
                        Cloudinary account, the public ID of the image is required to source this images for use in
                        gatsby-image </Text>


export default SinglePage

In the above code, getFluidImageObject is an asynchronous function, which is called on page load through useEffect. Once that function returns the image, you store it in the component’s fluid state with useState.

Next, you pass the following keys to getFluidImageObjects in its object argument:

  • public_id: The public ID of the Cloudinary image

  • cloudName: The cloud name of your Cloudinary account

  • originalHeight: The height of the image to be fetched

  • originalWidth: The width of the image to be fetched

  • transformations: The transformations Cloudinary applies to the returned image

See the complete keys along with their optional and required arguments.

getFluidImageObject passes transformations in the transformation’s key to add a purple effect and to horizontally flip the image with the e_replace_color:purple and a_hflip parameters Cloudinary transformations respectively.

With getFluidImageObjects, you can fetch with gatsby-image any image in your Cloudinary account for display on the page.

The image looks like this before transformation: After transformation, it looks like this:

gatsby-image lazy-loads images that are sourced with getFluidImageObject.

Update of Homepage

Finally, add a button to the homepage for navigating to the image that you just sourced. To accomplish that task, edit the IndexPage component in the src/pages/index.js file to read as follows:

import React from "react"
import { graphql, Link, useStaticQuery } from "gatsby";
import Layout from "../components/layout"
import SEO from "../components/seo"
import Image from "gatsby-image"
import { Box, Button, Heading, Text } from "@chakra-ui/core/dist";

const IndexPage = () => {
    // fetch images
    const data = useStaticQuery(graphql`query BannerImage {
      bannerImage: file(name: { eq: "7" }) {
        cloudinary: childCloudinaryAsset {
          fluid(transformations:["e_grayscale"] maxWidth: 1500) {

    const bannerImage = data.bannerImage.cloudinary.fluid;

    return (
            <SEO title="Home"/>
            <Box mb={[10, 20, 100]}>
                <Heading size={'xl'} m={3} textAlign={"center"}>Responsive Banner Image</Heading>
                    <Image fluid={bannerImage}/>
            <Text my={5}>Click any of the buttons below to see the gallery or single Image with
                the <i>getFluidImageObject</i> API</Text>

                <Button variantColor={'teal'} mr={10} mb={[2, 0, 0]}>
                    <Link to="/gallery"> Gallery Images</Link>

                {/_Button to single page with getFluidImageAPI_/}
                <Button variantColor={'green'} mb={[2, 0, 0]}>
                    <Link to="/single">API Image</Link>

export default IndexPage

In the above code, Chakra UI styles the components for a responsive layout and responsive typography, with breakpoints for mobile, tablet, and desktop.

Now restart the development server for the updated look of the webpage.

Notice the lazy-loaded image?

As a reference, here's the deployed app on Netlify. The complete code is in the GitHub repository.


You now know how to fetch images with getFluidImageObject from Cloudinary into gatsby-image for GatsbyJS projects. getFixedImageObject fetches fixed images for gatsby-image in a similar manner.

Coming up is part 3, which describes how to add a dark mode as a toggle for the website and convert the site to a progressive web app (PWA) with only a few lines of code. Pretty amazing.

Like this article? Follow @iChuloo on Twitter