Strapi blog logo
  • Product

      Why Strapi?Content ArchitectureRoadmapIntegrationsTry live demo
      OverviewContent Types BuilderCustomizable APIMedia LibraryRoles & Permissions
      Discover Strapi Enterprise EditionDiscover our partners
  • Pricing

  • Solutions

      Static WebsitesMobile ApplicationsCorporate websitesEditorial SitesEcommerce
      Delivery HeroL'EquipeSociete GeneralePixelDustBanco International
      Discover all our user stories
  • Community

      CommunityWrite for the communityWall of LoveStrapi Conf 2021
      SlackGitHubYoutubeCommunity Forum
      Meet the Strapi Community StarsDiscover the Strapi Showcase
  • Resources

      BlogStartersNewsroomSupport
      Strapi AcademyTutorialsVideos GuidesWebinars
      The Guide to Headless CMS Strapi Community Forum
  • Docs

      Getting StartedContent APIConfigurationInstallationDeploymentMigration
      Getting StartedContent ManagerContent-Types BuilderUsers, Roles & PermissionsPlugins
      Developer DocumentationStrapi User Guide

Looking for our logo ?

Logo Brand download
Download Logo Pack
See more Strapi assets
Strapi blog logo
  • Product

    Product

    • Why Strapi?
    • Content Architecture
    • Roadmap
    • Integrations
    • Try live demo

    Features

    • Overview
    • Content Types Builder
    • Customizable API
    • Media Library
    • Roles & Permissions
    • Discover Strapi Enterprise Edition
    • Discover our partners
    Features cover

    Unlock the full potential of content management

    See all features
    Strapi Enterprise Edition

    Discover the advanced features included in Strapi Enterprise Edition.

    Get Started
  • Pricing
  • Solutions

    Solutions

    • Static Websites
    • Mobile Applications
    • Corporate websites
    • Editorial Sites
    • Ecommerce

    Stories

    • Delivery Hero
    • L'Equipe
    • Societe Generale
    • PixelDust
    • Banco International
    • Discover all our user stories
    Delivery Hero team

    Delivery Hero manages their partner portal with Strapi.

    Read their story
    turn 10 studios website

    How 1minus1 delivered a creative website for Turn10 Studios 25% faster with Strapi

    Discover their story
  • Community

    Community

    • Community
    • Write for the community
    • Wall of Love
    • Strapi Conf 2021

    Resources

    • Slack
    • GitHub
    • Youtube
    • Community Forum
    • Meet the Strapi Community Stars
    • Discover the Strapi Showcase
    Strapi Conf

    The first Strapi Global User Conference.

    Register now
    Write for the community

    Contribute on educational content for the community

    Discover the program
  • Resources

    Resources

    • Blog
    • Starters
    • Newsroom
    • Support

    Learning

    • Strapi Academy
    • Tutorials
    • Videos Guides
    • Webinars
    • The Guide to Headless CMS
    • Strapi Community Forum
    Introducing Strapi Academy

    Everything you need to know to master Strapi.

    Go to the academy
    Strapi Repository on GitHub

    Get started with the Strapi repository

    Go to repository
  • Docs

    Developers

    • Getting Started
    • Content API
    • Configuration
    • Installation
    • Deployment
    • Migration

    User Guide

    • Getting Started
    • Content Manager
    • Content-Types Builder
    • Users, Roles & Permissions
    • Plugins
    • Developer Documentation
    • Strapi User Guide
    Install Strapi

    Install Strapi locally or wherever you need.

    Get Started
    Migration Guides Strapi

    Using a previous version of Strapi? Migrate to the latest.

    Read Guides
Get Started
Back to articles

Adding Cloudinary support to your Strapi Application

Adding Cloudinary support to your Strapi Application
  • Share on facebook
  • Share on linkedin
  • Share on twitter
  • Share by email

Cretu Razvan

Hi there!

In today's article, I will show you how to simply change the default upload provider of your Strapi application to Cloudinary. It is really easy and very straight forward. I will be creating a single page blog using Strapi with Cloudinary provider as our back-end and NextJS framework to build our front-end website.

Prerequisites

To follow along with this tutorial you will need to have the following installed on your machine:

  • Node.js V10+
  • npm or yarn
  • A Cloudinary account

What is Cloudinary?

As stated on their FAQs page, Cloudinary is a very useful image and video management solution for websites and mobile apps. It covers everything from image and video uploads, storage, manipulations, optimizations to delivery. Cloudinary can deliver up to terabytes of data through a fast Content Delivery Network (CDN).

Set-up Cloudinary

One of the first things you will need to do is to create a free account on Cloudinary right here. Once you managed to create your free account you will be redirected to the management dashboard of your account.

On the dashboard page you will find your Account Details that you will need to save for later:

  • Cloud name
  • API Key
  • API Secret

Make sure to keep these details secret and do not share them with anyone.

Back-end set-up

Open up a terminal of your choice and navigate to the folder you want your project stored. I will create mine under C:\Projects, but you can store it wherever you want.

To follow along with this tutorial you will need an already up and running Strapi project or simply create one with the following command:

yarn create strapi-app strapi-cloudinary --quickstart

Once the creation of your project is completed you will be prompted to <http://localhost:1337/admin> in order to create the first admin user for your project and to log in into the administration panel.

After you managed to get into your administration panel head to Content-Types Builder and create a collection-type called Posts with it's required fields in order to store post related data for our blog:

  • title: text (short text)
  • published_date: datetime
  • cover: media (single media)
  • content: rich text

Now make sure to add permissions to your Posts collection-type so it will be available to unauthenticated users on your site. Go under Settings > Roles ( Users & Permissions plugin ) > Public and simply check the boxes next to find and findOne actions for the posts endpoint.

Now that we have our project set-up open the project's folder with your favourite IDE and install strapi-provider-upload-cloudinary package to your project along with graphql so we can query for our data through the GraphQL endpoint.

Run this line inside your project's location and you should be good to go:

yarn add strapi-provider-upload-cloudinary graphql

Make sure your Strapi server is not running at the moment of installation, you can restart it right after.

After completion, create the following file ./config/plugins.js and add the below lines of code to it:

module.exports = ({ env }) => ({
    // ...
    upload: {
      provider: 'cloudinary',
      providerOptions: {
        cloud_name: env('CLOUDINARY_NAME'),
        api_key: env('CLOUDINARY_KEY'),
        api_secret: env('CLOUDINARY_SECRET'),
      },
    },
    // ...
  });

Under the root directory of your project create a .env file and add the following variables and with their respective values. These can be found in your Cloudinary dashboard under Account Details:

CLOUDINARY_NAME = cloudinary-name
CLOUDINARY_KEY = cloudinary-key
CLOUDINARY_SECRET = cloudinary-secret

Now that we finished with the coding part restart the Strapi server and access from your browser the following route <http://localhost:1337/graphql>. In order to use your data you will need to run the below query inside the GraphQL playground:

s_0531D56359EF0D63D9ED9445D38CA7500CE99D2C0FFD08678BC1154E4370F710_1605484966228_image.png

You can see that now our cover URL is a Cloudinary one.

Front-end set-up

Great, now let's begin by creating our front-end application so we can display our images. I will be using NextJS for this tutorial but you can use any front-end framework you are comfortable with.

Inside a terminal of your choice create a folder where you would like your project to be stored and navigate to it.

One of the first things you will need to do is to install the create-next-app package globally by running one of the following commands:

yarn global add @create-next-app/core

or

npm install --global @create-next-app/core

Once everything installed successfully you can start creating your NextJS application. The following line will do all the hassle for you which will set-up a quickstart template.

yarn create next-app frontend-cloudinary

To make sure everything installed correctly simply start your app with:

yarn dev

Before continuing the development let's install a few more dependencies that will be used throughout the application.

yarn add @apollo/react-hooks apollo-cache-inmemory apollo-client apollo-link-http graphql graphql-tag isomorphic-unfetch next-with-apollo

I will be using Apollo in order to interact with the GraphQL endpoint from the Strapi server. The set-up is based on this article. Make sure to check it out for a more detailed description of the following lines of code.

Under the root directory of your front-end app create the following file ./utils/apollo.js and paste the following code inside:

import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import withApollo from "next-with-apollo";
import { createHttpLink } from "apollo-link-http";
import fetch from "isomorphic-unfetch";

const link = createHttpLink({
  fetch, 
  uri: "http://localhost:1337/graphql"
});

export default withApollo(
  ({ initialState }) => new ApolloClient({
      link: link,
      cache: new InMemoryCache().restore(initialState || {})
    })
);

Under the root directory of your front-end app create the following file `./utils/apollo.js and paste the following code inside:QL endpoint anywhere in the application. Paste the following code inside:

import '../styles/globals.css'
import React from "react";
import { ApolloProvider } from "@apollo/react-hooks";
import withData from "../utils/apollo";

function MyApp({ Component, pageProps, apollo }) {
  return (
    <ApolloProvider client={apollo}>
      <Component {...pageProps} />
    </ApolloProvider>
  )
}

export default withData(MyApp)

For more details about the _app.js file read here.

One of the next steps is to create a reusable Query component so that we can use it anywhere in our app. It will wrap your other components so that each time you will need to fetch data from your GraphQL endpoint, it will pass down the data as props to the children components.

The component will look like so:

import React from "react";
import { useQuery } from "@apollo/react-hooks";

const Query = ({ children, query }) => {
  const { data, loading, error } = useQuery(query);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {JSON.stringify(error)}</p>;

  return children({ data });
};

export default Query;

One last thing to do before putting everything together is to create the actual GraphQL query. Create the following file ./apollo/queries/posts/posts.js and add the below code inside it:

import gql from "graphql-tag";

const POSTS_QUERY = gql`
query Posts {
    posts {
      id
      title
      content
      published_at
      cover {
        url
      }
    }
  }
`;

export default POSTS_QUERY;

Now that we have everything ready for our app, let's start by setting it up together.

You will use the Next's Image component to render the images hosted on Cloudinary.

The Image component is provided by Next.js as of version 10.0.0. It allows for Automatic Image Optimization that will work with any image source you like. You will have optimized images even if you host them on an external data source, like in our case.

Make sure to check more about the Image component and what it provides.

In order to have your images from Cloudinary optimized you will have to make the following changes to the next.config.js file:

module.exports = {
    images: {
      domains: ["res.cloudinary.com"],
    },
  }

On the other hand, if you don't want your image to be optimized by the component you could set the unoptimized prop to true. Like so, the configuration above is not mandatory.

The code in your index.js file can simply be overwritten by the following:

import Head from 'next/head'
import styles from '../styles/Home.module.css'
import Query from "../components/query";
import POSTS_QUERY from "../apollo/queries/posts/posts";
import Image from 'next/image'
import Moment from "react-moment";

export default function Home() {
  return (
    <div className={styles.container}>
      <Query query = {POSTS_QUERY}>
        {({data: {posts}}) => {
            return(
            <div>
              <Head>
                <title>Create Next App</title>
                <link rel="icon" href="/favicon.ico" />
              </Head>
 
              <main className={styles.main}>
                <h1 className={styles.title}>
                  Welcome to <a href="https://nextjs.org">Next.js!</a>
                </h1>
                <p className={styles.description}>
                  Get started by editing{' '}
                  <code className={styles.code}>pages/index.js</code>
                </p>
                <div className = {styles.grid}> 
                  {posts.map((post) => {
                    return (
                      <div className = {styles.card}>
                        <div className = {styles.image}>
                          <Image src = {post.cover.url} layout = "fill"></Image>
                        </div>
                        <h1>{post.title}</h1>
                        <p>
                            <Moment format="MMM Do YYYY">{post.published_at}</Moment>
                        </p>
                      </div>
                    )
                  })}
                </div>
              </main>
              <footer className={styles.footer}>
                <a
                  href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
                  target="_blank"
                  rel="noopener noreferrer"
                >
                  Powered by{' '}
                  <img src="/vercel.svg" alt="Vercel Logo" className={styles.logo} />
                </a>
              </footer>
            </div>
            )
          }
        }
      </Query>
    </div>
  )

Now if you start your application with yarn develop your images should be nicely displayed on the home page.

s_0531D56359EF0D63D9ED9445D38CA7500CE99D2C0FFD08678BC1154E4370F710_1607476502519_image.png

Conclusion

At the end of this article, you should easily change the default Strapi provider to Cloudinary. You can check more about other upload providers on the Strapi documentation here or on npmjs. You can even create one of your own.

  • Share on facebook
  • Share on linkedin
  • Share on twitter
  • Share by email

You might also be interested in...

  • Guides & Tutorials

Deliveroo clone with Nuxt.js, GraphQL, Strapi and Stripe (4/7)

Tutorial for implementing Nextjs, Strapi, GraphQL, Stripe into a sample application to SSR applications and manage content with Strapi part (4/7)

Ryan Belke

Ryan Belke

November 12, 2018

Strapi Starter Nuxt Blog
  • Guides & Tutorials

Strapi Starter Nuxt Blog

Bootstrap a simple blog application using Nuxt.js and Strapi, the most suitable headless CMS for Nuxt.js

Maxime Castres

March 5, 2020

Understanding Headless Architecture: What Is It?
  • Strapi
  • Content Management

Understanding Headless Architecture: What Is It?

What is the difference between headless architecture and other CMSs? Here is everything you need to know about this forward-looking solution.

Victor Coisne

Victor Coisne

November 9, 2020

Unleash content.

Read the docs
Get Started

Strapi is the most popular open-source Headless CMS. Strapi gives developers the freedom to use their favorite tools and frameworks while allowing editors to easily manage their content and distribute it anywhere.

Product

  • Why Strapi?
  • Content Architecture
  • Features
  • Enterprise Edition
  • Partner Program
  • Roadmap
  • Support
  • Integrations
  • Try live demo

Resources

  • How to get started
  • Meet the community
  • Tutorials
  • API documentation
  • GitHub repository
  • Starters
  • Strapi vs Wordpress
  • The Guide to headless CMS

Integrations

  • Gatsby CMS
  • React CMS
  • Vue.js CMS
  • Nuxt.js CMS
  • Next.js CMS
  • Angular CMS
  • Gridsome CMS
  • Jekyll CMS
  • 11ty CMS
  • Svelte CMS
  • Sapper CMS
  • Ruby CMS
  • Python CMS

Company

  • About us
  • Blog
  • Careers
  • Contact
  • Newsroom
  • © 2021, Strapi
  • LicenseTermsPrivacy