Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

gatsby-transformer-cloudinary

cloudinary-devs55.5kMIT4.7.0TypeScript support: included

Transform local files into Cloudinary-managed assets for Gatsby sites.

gatsby, gatsby-plugin, image, cloudinary

readme

Gatsby Transformer Cloudinary

With gatsby-transformer-cloudinary you may:

  • 🖼️ Add gatsby-plugin-image support to any GraphQL Types describing a Cloudinary assets.
  • 📤 Upload local and remote images to Cloudinary from within your Gatsby project.

📥 But if you want to pull data from your Cloudinary account into the Gatsby data layer use our other plugin, gatsby-source-cloudinary

This is a community library supported by the Cloudinary Developer Experience team.

📖 Table of Contents

 

🖼️ Add Gatsby Image Support to Existing Cloudinary Assets

Information about Existing Cloudinary Assets is sourced into the Gatsby data layer using a plugin like gatsby-source-contentful, gatsby-source-sanity etc. or a custom source plugin.

  • The plugin adds the gatsbyImageData resolver to the sourced GraphQL Types configured.

The GraphQL Type must describe an existing Cloudinary asset and contain the following data.

Install Packages

npm install gatsby-transformer-cloudinary gatsby-plugin-image

or

yarn add gatsby-transformer-cloudinary gatsby-plugin-image

Configure Plugins

// File: ./gatsby-config.js

module.exports = {
  plugins: [
    // Some source plugin creating a GraphQL Type named `BlogPostHeroImage`
    {
      resolve: `gatsby-transformer-cloudinary`,
      options: {
        transformTypes: [
          // Assumes a GraphQL Type named `BlogPostHeroImage`
          // Could be a `BlogPost` node with a `heroImage` field
          // with the required data shape
          `BlogPostHeroImage`,
        ],
        // Optional transformation option
        defaultTransformations: ['c_fill', 'g_auto', 'q_auto'],
      },
    },
    `gatsby-plugin-image`,
  ],
};

Example Usage

// File: ./pages/{BlogPost.slug}.js

import React from 'react';
import { graphql } from 'gatsby';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';

const BlogPost = ({ data }) => {
  const { blogPost } = data;
  const gatsbyImage = getImage(blogPost.heroImage);
  return (
    <article>
      <h1>{blogPost.title}</h1>
      <GatsbyImage image={gatsbyImage} aria-hidden="true" alt="Hero Image" />
      {/* ... */}
    </article>
  );
};

export const query = graphql`
  query BlogPostById($id: String!) {
    blogPost(id: { eq: $id }) {
      title
      heroImage {
        gatsbyImageData(
          height: 300
          aspectRatio: 2
          placeholder: TRACED_SVG
          transformations: ["c_fill", "e_grayscale"]
        )
      }
    }
  }
`;

export default BlogPost;

Transform Type Requirements

Gatsby Image support may be added to any GraphQL Type describing a Cloudinary asset with the following data:

{
  // Required
  cloud_name: "my-amazing-blog",
  public_id: "blue-blue-blue",
  // Optional: Saves a network request for size/format data per image queried if all are added
  heigh: 360,
  width: 820,
  format: "jpg",
  // Optional: Saves a Cloudinary transformation per image queried with `placeholder=BLURRED` as this value will be used instead
  base64: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mMMXG/8HwAEwAI0Bj1bnwAAAABJRU5ErkJggg==",
  // Optional: Saves a Cloudinary transformation per image queried with `placeholder=TRACED_SVG` as this value will be used instead
  tracedSVG: "data:image/svg+xml,%3Csvg%20height%3D%229999%22%20viewBox%3D%220%200%209999%209999%22%20width%3D%229999%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22m0%200h9999v9999h-9999z%22%20fill%3D%22%23f9fafb%22%2F%3E%3C%2Fsvg%3E",
}

If the GraphQL Type does not have the required data shape, you may configure how to resolve the data using the transformTypes configuration option:

// File: ./gatsby-config.js

module.exports = {
  plugins: [
    // Some source plugin creating a GraphQL Type named `BlogPostHeroImage`
    {
      resolve: `gatsby-transformer-cloudinary`,
      options: {
        transformTypes: [
          {
            type: `CustomType`,
            // Use a static value
            cloudName: 'my-cld-cloud',
            // Resolve a value using a function
            height: (data) => data.metadata?.height,
          },
        ],
        // Optional transformation option
        defaultTransformations: ['c_fill', 'g_auto', 'q_auto'],
      },
    },
    `gatsby-plugin-image`,
  ],
};

To find the GraphQL Type describing your Cloudinary assets use the built-in GraphiQL exlorer](https://www.gatsbyjs.com/docs/how-to/querying-data/running-queries-with-graphiql/). Either hover over the field describing the asset or look in the "Documentation Explorer".

defaultBase64 and defaultTracedSVG is the base64 URI of the placeholder image, it must comply with RFC 2397.

Private CDNs and custom delivery hostnames (CNAMEs)

If you are using a private CDN or a custom delivery hostname (CNAME) you may configure the plugin to do so. Read more about Private CDNs and CNAMEs.

// File: ./gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-cloudinary`,
      options: {
        transformTypes: [
          {
            type: `CloudinaryAsset`,
            secureDistribution: 'my-domain.com',

            // Or using privateCdn
            // privateCdn: true,

            // Or using cname
            // secure: false,
            // cname: 'my-domain.com',
          },
        ],
        // Optional transformation option
        defaultTransformations: ['c_fill', 'g_auto', 'q_auto'],
      },
    },
    `gatsby-plugin-image`,
  ],
};

Sanity.io Configuration

If you are using Sanity.io and the gatsby-source-sanity plugin use the following configuration to add the gatsbyImageData resolver to the sourced Sanity Cloudinary assets:

// File: ./gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-sanity`,
      options: {
        projectId: process.env.SANITY_PROJECT_ID,
        dataset: process.env.SANITY_DATASET,
        token: process.env.SANITY_TOKEN,
      },
    },
    {
      resolve: `gatsby-transformer-cloudinary`,
      options: {
        transformTypes: [
          {
            type: 'SanityCloudinaryAsset',
            // Dynamically get the cloud name
            // from SanityCloudinaryAsset.url
            cloudName: (data) => {
              const findCloudName = new RegExp('(cloudinary.com/)([^/]+)', 'i');
              const result = data.url.match(findCloudName);
              return result[1];
            },
            // Or set it statically if all assets are from the same Cloudinary account
            // cloudName: "my-cld-cloud",
          },
        ],
      },
    },
    `gatsby-plugin-image`,
  ],
};

Contentful Configuration

If you are using Contentful and the gatsby-source-contentful plugin use the following configuration to add the gatsbyImageData resolver to the sourced Cloudinary assets:

// File: ./gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-contentful`,
      options: {
        spaceId: process.env.CONTENTFUL_SPACE_ID,
        accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
      },
    },
    {
      resolve: `gatsby-transformer-cloudinary`,
      options: {
        transformTypes: [
          {
            // ❗❕ Replace `contentfulBlogPostFeaturedImageJsonNode`
            // with the name of the GraphQL Type describing your Cloudinary assets
            // will always start with `contentful` and end with `JsonNode`
            type: 'contentfulBlogPostFeaturedImageJsonNode',

            // Dynamically get the cloud name
            // from SanityCloudinaryAsset.url
            cloudName: (data) => {
              const findCloudName = new RegExp('(cloudinary.com/)([^/]+)', 'i');
              const result = data.url.match(findCloudName);
              return result[1];
            },
            // Or set it statically if all assets are from the same cloud
            // cloudName: 'my-cld-cloud',
          },
        ],
      },
    },
    `gatsby-plugin-image`,
  ],
};

 

📤 Upload Local Images and Add Gatsby Image Support

If you upload local images to Cloudinary and skip the gatsby-transformer-sharp you speed up your build process and enjoy Cloudinary's transformations:

  • The plugin creates a CloudinaryAsset node for each image.
  • The plugin adds a gatsbyImageData resolver to each node by default.

This configuration and example assumes you have your images folder in the root of your project.

Install packages

npm install gatsby-transformer-cloudinary gatsby-source-filesystem gatsby-plugin-image

or

yarn add gatsby-transformer-cloudinary gatsby-source-filesystem gatsby-plugin-image

Configure plugins

// File: ./gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `gallery`,
        path: `${__dirname}/gallery`,
      },
    },
    {
      resolve: 'gatsby-transformer-cloudinary',
      options: {
        // Required for uploading
        cloudName: process.env.CLOUDINARY_CLOUD_NAME,
        apiKey: process.env.CLOUDINARY_API_KEY,
        apiSecret: process.env.CLOUDINARY_API_SECRET,
        // Optional uploading options
        uploadFolder: process.env.CLOUDINARY_UPLOAD_FOLDER,
        uploadSourceInstanceNames: ['gallery'],
        overwriteExisting: process.env.NODE_ENV === 'production' ? true : false,
        // Optional transformation options
        transformTypes: ['CloudinaryAsset'],
        defaultTransformations: ['c_fill', 'g_auto', 'q_auto'],
      },
    },
  ],
};

process.env ⁉️ Read about env variables in the Gatsby docs.

Example Usage

Example of the plugin fetching an asset using the useStaticQuery API of Gatsby:

// File ./components/local-upload.js

import React from 'react';
import { graphql, useStaticQuery } from 'gatsby';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';

const LocalUploadExample = () => {
  // Using gatsby-transformer-sharp
  // commented out for comparison

  // const data = useStaticQuery(graphql`
  //   query {
  //     file(name: { eq: "sergey-semin-unsplash" }) {
  //       childImageSharp {
  //         gatsbyImageData(height: 300, layout: FIXED)
  //       }
  //     }
  //   }
  // `);

  const data = useStaticQuery(graphql`
    query {
      file(name: { eq: "sergey-semin-unsplash" }) {
        childCloudinaryAsset {
          gatsbyImageData(height: 300, layout: FIXED)
        }
      }
    }
  `);

  // const gatsbyImage = getImage(data.file.childImageSharp);
  const gatsbyImage = getImage(data.file.childCloudinaryAsset);

  return (
    <GatsbyImage
      image={gatsbyImage}
      alt="Pirate photo by Sergey Semin from Unsplash."
    />
  );
};

export default LocalUploadExample;

 

📤 Upload Remote Images and add Gatsby Image Support

Upload remote images referenced in any node to Cloudinary and enjoy Cloudinary's transformations:

  • The plugin creates a CloudinaryAsset node for each image.
  • The plugin adds the gatsbyImageData resolver to each node by default.

Uploading remote image requires you to write some custom code. We'd like to make it configurable instead, let us know if you'd benefit by joining the discussion.

This configuration and example assumes your Gatsby Data Layer has at least one node of type Project with a coverImageUrl field containg a url pointing to a publically available image file.

Install Packages

npm install gatsby-transformer-cloudinary gatsby-plugin-image

or

yarn add gatsby-transformer-cloudinary gatsby-plugin-image

Configure Plugins

// File: ./gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-transformer-cloudinary',
      options: {
        // Required for uploading
        cloudName: process.env.CLOUDINARY_CLOUD_NAME,
        apiKey: process.env.CLOUDINARY_API_KEY,
        apiSecret: process.env.CLOUDINARY_API_SECRET,
        // Optional uploading options
        uploadFolder: process.env.CLOUDINARY_UPLOAD_FOLDER,
        overwriteExisting: process.env.NODE_ENV === 'production' ? true : false,
        // Optional transformation options
        transformTypes: ['CloudinaryAsset'],
        defaultTransformations: ['c_fill', 'g_auto', 'q_auto'],
      },
    },
  ],
};

process.env ⁉️ Read about env variables in the Gatsby docs.

Example Usage

// File: ./gatsby-node.js

import { createRemoteImageNode } from 'gatsby-transformer-cloudinary';

export async function onCreateNode({
  node,
  actions: { createNode },
  createNodeId,
  createContentDigest,
  reporter,
}) {
  if (node.internal.type === 'Project' && node.coverImageUrl) {
    // Upload the image to Cloudinary
    const imageNode = await createRemoteImageNode({
      url: node.coverImageUrl,
      parentNode: node,
      createNode,
      createNodeId,
      createContentDigest,
      reporter,
    });

    // Add node field to be used by "createSchemaCustomization"
    createNodeField({ node: node, name: 'coverImage', value: imageNode.id });
  }
}

exports.createSchemaCustomization = (gatsbyUtils) => {
  const { actions } = gatsbyUtils;

  // Connect the node to the CloudinaryAsset using @link
  const ProjectType = `
      type Project implements Node  {
        coverImageUrl: String!
        coverImage: CloudinaryAsset @link(from: "fields.coverImage" by: "id")
      }
    `;

  actions.createTypes([ProjectType]);
};
// File: ./pages/{Article.slug}.js

import React from 'react';
import { graphql } from 'gatsby';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';

const Project = ({ data }) => {
  const { project } = data;
  const gatsbyImage = getImage(project.coverImage);
  return (
    <article>
      <h1>{project.name}</h1>
      <GatsbyImage image={gatsbyImage} aria-hidden="true" alt="Cover Image" />
      {/* ... */}
    </article>
  );
};

export const query = graphql`
  query ProjectById($id: String!) {
    project(id: { eq: $id }) {
      name
      coverImage {
        gatsbyImageData(
          height: 300
          aspectRatio: 2
          placeholder: TRACED_SVG
          transformations: ["c_fill", "g_auto:subject", "q_auto"]
        )
      }
    }
  }
`;

export default Project;

 

🔌 Plugin Options

In gatsby-config.js the plugin accepts the following options:

cloudName (required for upload functionality)

You'll find your Cloudinary account's cloudName in your Cloudinary console.

Type: String\ Default: n/a\ Note: Store and retrieve your cloudName as an environment variable.

apiKey (required for upload functionality)

You'll find your Cloudinary API Key in the Cloudinary console.

Type: String\ Default: n/a\ Note: Store and retrieve your apiKey as an environment variable.

apiSecret (required for upload functionality)

You'll find your Cloudinary API Secret in your Cloudinary console.

secure

When set to false uses http instead of https for the image urls.

Type: Boolean Default: true

height / width

Type: String\ Default: n/a\ Note: Store and retrieve your apiSecret as an environment variable.

uploadFolder

An optional folder name where the uploaded assets will be stored on Cloudinary.

Type: String\ Default: n/a\

uploadSourceInstanceNames

An optional array limiting uploads to file nodes with a matching sourceInstanceName.

Type: [String]\ Default: n/a\

transformTypes

An optional array of GraphQL Types to add the gatsbyImageData resolver for Gatsby Image support.

Type: [String] | [Object]\ Default: ['CloudinaryAsset']

overwriteExisting

Whether to overwrite existing assets with the same public ID. When set to false, return immediately if an asset with the same Public ID was found. It's recommended that this is set to false in development as each image overwrite costs one Cloudinary transformation.

Type: Boolean\ Default: false

defaultTransformations

The default value for the gatsbyImageData resolver argument transformations.

Type: [String]\ Default: ['c_fill', 'g_auto', 'q_auto']

 

🖼️ Gatsby Plugin Image (gatsbyImageData) API

The plugin supports gatsby-plugin-image by adding a gatsbyImageData resolver to the configured GraphQL types.

Arguments for gatsbyImageData

transformations

An array of "raw" cloudinary transformations added to the initial transformation together with the width and height.

Type: [String]\ Default:["c_fill", "g_auto", "q_auto"] or the configured defaultTransformations\ Example: ["c_crop", "x_300"]

WARNING: Changing the sizing using transformations will mess with the Gatsby Image Component

chained

An array of "raw" cloudinary transformations added after the initial transformations above.

Type: [String]\ Default: []\ Example: ["e_grayscale","e_pixelate_faces,e_tint:100:663399:0p:white:100p"]

WARNING: Changing the sizing using chained transformations will mess with the Gatsby Image Component

placeholder

The style of the temporary image shown while the larger image is loaded.

Type: NONE, BLURRED or TRACED_SVG\ Default: NONE\ Example: BLURRED

NOTE: DOMINANT_COLOR is not supported

Read the Gatsby Plugin Image Docs for more information.

height / width

Read the Gatsby Plugin Image Docs on height / width.

aspectRatio

Read the Gatsby Plugin Image Docs on aspectRatio.

layout

Read the Gatsby Plugin Image Docs on layout.

backgroundColor

Read the Gatsby Plugin Image Docs on backgroundColor.

breakpoints

Read the Gatsby Plugin Image Docs on breakpoints.

outputPixelDensities

Read the Gatsby Plugin Image Docs on outputPixelDensities.

sizes

Read the Gatsby Plugin Image Docs on sizes.

secure

When set to false use non-secure URLs (http) instead of secure URLs(https) for the image URLs.

Type: Boolean\ Default: true

secureDistribution

The custom domain name (CNAME) to use for building secure URLs (https).

Relevant only for users on the Advanced plan or higher that have a custom CNAME. For details, see Private CDNs and CNAMEs.

Type: String\ Default: n/a

cname

The custom domain name (CNAME) to use for building non-secure URLs (http), remember to set secure to false when using cname.

Relevant only for users on the Advanced plan or higher that have a custom CNAME. For details, see Private CDNs and CNAMEs.

Type: String\ Default: n/a

privateCdn

Relevant only for users on the Advanced plan or higher that have private CDN distribution. For details, see Private CDNs and CNAMEs.

Type: Boolean\ Default: false

 

📚 Other Resources

 

🏴‍☠️ Contribute

You may improve the documentation, help fellow users, report bugs, suggest enhancements, contribute code and more.

Get started by reading the contribution docs.

changelog

4.7.0 (2024-08-30)

Features

  • simplify transformTypes configuration and allow "Advanced CDN Media Asset Delivery Options" (#254) (d4ed539)

4.7.0-beta.1 (2024-07-28)

Features

  • simplify transformTypes configuration and allow "Advanced CDN Media Asset Delivery Options" (#254) (d4ed539)

4.6.0 (2024-06-07)

Features

4.6.0-beta.2 (2024-06-07)

Features

4.6.0-cname-private-cdn-support.1 (2024-06-06)

Features

4.6.0-beta.1 (2024-02-13)

Features

4.5.0 (2023-08-01)

Features

4.4.0 (2023-03-12)

Features

4.3.1 (2023-01-17)

Bug Fixes

4.3.0 (2022-12-21)

Features

4.2.0 (2022-12-20)

Bug Fixes

  • gatsbyImageData generates http urls, not https (#210) (3508cd3), closes #209
  • peer dependency (gatsby-plugin-image) (#212) (3f40130)

Features

  • allow invalid source data by making gatsbyImageData nullable (#218) (acf28f9), closes #214

4.1.0 (2022-10-26)

Features

4.0.1 (2022-10-10)

Performance Improvements

  • remove upload code only needed by gatsby-image (#197) (576f30f), closes #188

4.0.0 (2022-10-10)

Features

  • remove support for gatsby-image - deprecated Gatsby plugin (#195) (d451b8e)

BREAKING CHANGES

  • Removed support for gatsby-image (ie. fixed and fluid), use gatsby-plugin-image (ie. gatsbyImageData instead.

3.1.0 (2022-12-20)

Features

  • allow invalid source data by making gatsbyImageData nullable (#218) (acf28f9), closes #214

3.0.1 (2022-11-30)

Bug Fixes

  • gatsbyImageData generates http urls, not https (#210) (3508cd3), closes #209
  • peer dependency (gatsby-plugin-image) (#212) (3f40130)

Version 3.0.0

Fixes:

  • Remove direct mutation of nodes #156

BREAKING CHANGES:

  • CloudinaryAsset nodes are not added for existing assets described by a content node
  • When uploading remote images the relationship between parent and child node must must be handled manually
  • gatsbyImageData, fluid and fixed resolvers are only added to GraphQL Types configured using the transformTypes

Version 2.3.0

Additions:

  • Support for gatsby-plugin-image (adds the gatsbyImageData resolver)#90

Improvements:

  • publicId, cloudName and version available on CloudinaryAsset nodes #89
  • Limit files to upload by utilizing the added uploadSourceInstanceNames plugin option #71 and #103

Version 2.2.4

Fixes:

  • API key & secret is no longer required when using the plugin for only remote images.

Version 2.2.1

Additions:

  • Added types for fixedImageObject and fluidImageObject.

Fixes:

  • fixedImageObject and fluidImageObject uses default plugin options properly in runtime.
  • Moved fixedImageObject and fluidImageObject APIs to /api. Fixes fs error when importing from index.js.
  • Set default value for fieldsToSelect in fixedImageObject and fluidImageObject to empty array.

Version 2.2.0

Improvements:

  • Only throw an error on missing Cloudinary credentials if those credentials are actually needed to upload an image to Cloudinary.
  • base64 images are no longer generated unless a query requesting them is run.
  • defaultTracedSVG values are now passed along as tracedSVG values.
  • Improved base64 caching so that if a second request for the same base64 image is made before the first response is received, only one request is made.

Version 2.1.1

Additions:

  • Added logging for each time we have to fetch a base64 image from Cloudinary to explain long query steps in the Gatsby build process.

Fixes:

  • Fluid images use defaultBase64 images when they are provided.

Version 2.1.0

Additions:

  • Added the ability to use both width and height parameters simultaneously for fixed queries.
  • Added the ability to use precomputed base64 images. When precomputed base64 images are used, build times should improve and Cloudinary usage should decrease.

Fixes:

  • Deeply nested asset data is now transformed into CloudinaryAsset nodes.

Version 2.0.0

Changes:

  • This is a major version bump to call attention to the change in default behavior introduced in version 1.1.1. (f_auto and q_auto are no longer added to image URLs by default.)

Fixes:

  • Images uploaded using the createRemoteImageNode function respect the overwriteExisting argument when provided and fall back to using the overwriteExisting plugin option.

Version 1.1.3

Fixes:

  • Typo fix.

Version 1.1.2

Fixes:

  • Local images uploaded to Cloudinary now respect the overwriteExisting plugin option.

Version 1.1.1

Changes:

  • Added enableDefaultTransformations plugin option. When set to true, f_auto and q_auto are added to all source URLs automatically. Previously, this was on by default. This behavior is now opt-in.

Version 1.1.0

Additions:

  • Added ability to use existing Cloudinary images by marking nodes with cloudinaryAssetData: true and providing cloudName, publicId, originalHeight, and originalWidth properties.
  • Added an optional height argument to fixed queries.

Improvements:

  • Cache base64 images when running queries to prevent duplicate network requests.

Fixes:

  • Changed the public_id to be the relative path of files without the extension instead of just the file's name. This fixes an issue with childrenCloudinaryAsset nodes being created instead of childCloudinaryAsset nodes.

Version 1.0.1

Additions:

  • Added CloudinaryAssetFluidLimitPresentationSize fragment.
  • Added presentationHeight and presentationWidth to CloudinaryAssetFluid.

Version 1.0.0

Breaking changes:

  • The default for fluidMinWidth has been decreased from 200 to 50 to match Cloudinary defaults.
  • The default for createDerived has been changed to false.
  • The default for breakpointsMaxImages has been increased from 5 to 20 to match Cloudinary defaults.
  • Breakpoint calculations are no longer requested by default when uploading an image. (This is controlled by the new useCloudinaryBreakpoints option.)
  • Image uploads no longer overwrite images with the same public ID by default. (This is controlled by the new overwriteExisting option.)

Other changes:

  • Added createRemoteImageNode to allow uploading remote images directly to Cloudinary without downloading them locally first.
  • Added Jest tests.
  • Added the ability to calculate breakpoints locally to avoid consuming Cloudinary transformation credits while developing.
  • Increased the timeout when uploading images to Cloudinary from 60 seconds to 5 minutes.

Version 0.3.5

  • Beginning of changelog.