Product
Resources
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.
To follow along with this tutorial you will need to have the following installed on your machine:
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).
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:
Make sure to keep these details secret and do not share them with anyone.
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:
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:
You can see that now our cover URL is a Cloudinary one.
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.
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.