{blogPost.title}
{/ ... /}
Transform local files into Cloudinary-managed assets for Gatsby sites.
npm install gatsby-transformer-cloudinaryWith 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.
- š¼ļø Add Gatsby Image Support to Existing Cloudinary Assets
- Install Packages
- Configure Plugins
- Example usage
- Sanity.io Configuration
- Contentful Configuration
- š¤ Upload local images and add Gatsby Image Support
- Install Packages
- Configure Plugins
- Example usage
- š¤ Upload remote images and add Gatsby Image Support
- Install Packages
- Configure Plugins
- Example Usage
- š Pugin Options
- š¼ļø Gatsby Image API
- š Other Resources
- š“āā ļø Contribute
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.
``bash`
npm install gatsby-transformer-cloudinary gatsby-plugin-image
or
`bash`
yarn add gatsby-transformer-cloudinary gatsby-plugin-image
`js
// File: ./gatsby-config.js
module.exports = {
plugins: [
// Some source plugin creating a GraphQL Type named BlogPostHeroImagegatsby-transformer-cloudinary
{
resolve: ,BlogPostHeroImage
options: {
transformTypes: [
// Assumes a GraphQL Type named BlogPost
// Could be a node with a heroImage fieldBlogPostHeroImage
// with the required data shape
,gatsby-plugin-image
],
// Optional transformation option
defaultTransformations: ['c_fill', 'g_auto', 'q_auto'],
},
},
,`
],
};
`jsx
// 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 (
{blogPost.title}
{/ ... /}
);
};
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;
`
Gatsby Image support may be added to any GraphQL Type describing a Cloudinary asset with the following data:
`jsplaceholder=BLURRED
{
// 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 as this value will be used insteadplaceholder=TRACED_SVG
base64: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mMMXG/8HwAEwAI0Bj1bnwAAAABJRU5ErkJggg==",
// Optional: Saves a Cloudinary transformation per image queried with 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:
`js
// File: ./gatsby-config.js
module.exports = {
plugins: [
// Some source plugin creating a GraphQL Type named BlogPostHeroImagegatsby-transformer-cloudinary
{
resolve: ,CustomType
options: {
transformTypes: [
{
type: ,gatsby-plugin-image
// 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'],
},
},
,`
],
};
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.
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.
`js
// File: ./gatsby-config.js
module.exports = {
plugins: [
{
resolve: gatsby-transformer-cloudinary,CloudinaryAsset
options: {
transformTypes: [
{
type: ,
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,`
],
};
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:
`js
// File: ./gatsby-config.js
module.exports = {
plugins: [
{
resolve: gatsby-source-sanity,gatsby-transformer-cloudinary
options: {
projectId: process.env.SANITY_PROJECT_ID,
dataset: process.env.SANITY_DATASET,
token: process.env.SANITY_TOKEN,
},
},
{
resolve: ,gatsby-plugin-image
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",
},
],
},
},
,`
],
};
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:
`js
// File: ./gatsby-config.js
module.exports = {
plugins: [
{
resolve: gatsby-source-contentful,gatsby-transformer-cloudinary
options: {
spaceId: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
},
},
{
resolve: ,contentfulBlogPostFeaturedImageJsonNode
options: {
transformTypes: [
{
// āā Replace contentful
// with the name of the GraphQL Type describing your Cloudinary assets
// will always start with 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,`
],
};
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.gatsbyImageData
- The plugin adds a resolver to each node by default.
This configuration and example assumes you have your images folder in the root of your project.
`bash`
npm install gatsby-transformer-cloudinary gatsby-source-filesystem gatsby-plugin-image
or
`bash`
yarn add gatsby-transformer-cloudinary gatsby-source-filesystem gatsby-plugin-image
`js
// File: ./gatsby-config.js
module.exports = {
plugins: [
{
resolve: gatsby-source-filesystem,gallery
options: {
name: ,${__dirname}/gallery
path: ,`
},
},
{
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 of the plugin fetching an asset using the useStaticQuery API of Gatsby:
`jsx
// 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 (
alt="Pirate photo by Sergey Semin from Unsplash."
/>
);
};
export default LocalUploadExample;
`
Upload remote images referenced in any node to Cloudinary and enjoy Cloudinary's transformations:
- The plugin creates a CloudinaryAsset node for each image.gatsbyImageData
- The plugin adds the 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.
`bash`
npm install gatsby-transformer-cloudinary gatsby-plugin-image
or
`bash`
yarn add gatsby-transformer-cloudinary gatsby-plugin-image
`js
// 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.
`js
// 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]);
};
`
`jsx
// 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 (
{project.name}
{/ ... /}
);
};
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;
`
In gatsby-config.js the plugin accepts the following options:
You'll find your Cloudinary account's cloudName in your Cloudinary console.
Type: String\cloudName
Default: n/a\
Note: Store and retrieve your as an environment variable.
You'll find your Cloudinary API Key in the Cloudinary console.
Type: String\apiKey
Default: n/a\
Note: Store and retrieve your as an environment variable.
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: Booleantrue
Default:
#### height / width
Type: String\apiSecret
Default: n/a\
Note: Store and retrieve your as an environment variable.
An optional folder name where the uploaded assets will be stored on Cloudinary.
Type: String\
Default: n/a\
An optional array limiting uploads to file nodes with a matching sourceInstanceName.
Type: [String]\
Default: n/a\
An optional array of GraphQL Types to add the gatsbyImageData resolver for Gatsby Image support.
Type: [String] | [Object]\['CloudinaryAsset']
Default:
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\false
Default:
The default value for the gatsbyImageData resolver argument transformations.
Type: [String]\['c_fill', 'g_auto', 'q_auto']
Default:
) APIThe plugin supports gatsby-plugin-image by adding a gatsbyImageData resolver to the configured GraphQL types.
#### transformations
An array of "raw" cloudinary transformations added to the initial transformation together with the width and height.
Type: [String]\["c_fill", "g_auto", "q_auto"]
Default: or the configured defaultTransformations\["c_crop", "x_300"]
Example:
> 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: \["e_grayscale","e_pixelate_faces,e_tint:100:663399:0p:white:100p"]
Example:
> 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\NONE
Default: \BLURRED
Example:
> 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.
When set to false use non-secure URLs (http) instead of secure URLs(https) for the image URLs.
Type: Boolean\true
Default:
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
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
Relevant only for users on the Advanced plan or higher that have private CDN distribution. For details, see Private CDNs and CNAMEs.
Type: Boolean\false`
Default:
- Cloudinary image transformation reference
- Try the gatsby-source-cloudinary plugin to source media files into Gatsby file nodes
- Using Cloudinary image service for media optimization
- Watch Jason Lengstorf build this plugin's first version
You may improve the documentation, help fellow users, report bugs, suggest enhancements, contribute code and more.
Get started by reading the contribution docs.