{"id":28286,"date":"2023-05-22T07:00:00","date_gmt":"2023-05-22T14:00:00","guid":{"rendered":"http:\/\/upload-and-display-images-using-prisma"},"modified":"2025-11-26T16:49:48","modified_gmt":"2025-11-27T00:49:48","slug":"upload-and-display-images-using-prisma","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma","title":{"rendered":"Upload, Store, and Display Images Using Prisma"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Sometimes you need to handle and manage images linked to information that\u2019s stored in the database of your web application. You can improve and simplify both image management and data storage using two helpful products: Prisma and <a href=\"https:\/\/cloudinary.com\/\">Cloudinary<\/a>. In this article, we\u2019ll create a Next.js app to upload the images and display them as a gallery. To handle Prisma image upload, optimization, storage, and display, we\u2019ll use a <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">Cloudinary account<\/a>, which you can get right now for free and for life (no short term window limitations). To store image details, we\u2019ll use Prisma with a local SQLite database.<\/p>\n<h2>What is Prisma?<\/h2>\n<p>Prisma is an open-source ORM (object-relational mapping) for Node.js and TypeScript. It has a module to define the data models that will be used by the app, and their relationships, based on a Prisma Schema. The tool connects to a database (MySQL, PostgreSQL, SQLite) to store information related to the data models. There\u2019s also a Prisma Client module that offers an auto-generated query builder.<\/p>\n<p>To keep it simple, we\u2019ll be uploading images to Prisma like this:<\/p>\n<ul>\n<li>\n<p>Cloning your repository and installing dependencies.<\/p>\n<\/li>\n<li>\n<p>Configure your environment variables.<\/p>\n<\/li>\n<li>\n<p>Start the app.<\/p>\n<\/li>\n<li>\n<p>Create an API endpoint.<\/p>\n<\/li>\n<li>\n<p>Update your frontend to handle image upload.<\/p>\n<\/li>\n<\/ul>\n<h2>What is Cloudinary?<\/h2>\n<p>Cloudinary is a cloud-based service for managing media assets. You can upload, store, and manipulate images and videos with ease, and is ideal for handling the Prisma file upload process. As Cloudinary is offered as a software as a service (SaaS), it has servers that handle the upload, process, and delivery of media assets, with the possibility of expansion if your application\u2019s traffic increases.<\/p>\n<h2>What is Next.js?<\/h2>\n<p>Next.js is a popular React framework used to create user interfaces, static pages, and server-side rendered pages, and then combine them in the same application. It allows developers to create server-less API routes using Node.js logic.<\/p>\n<h2>Image Gallery App<\/h2>\n<p>Let\u2019s create an image gallery app with two pages: one to upload images, and another to list all the existing pictures. We\u2019ll upload the image files to Cloudinary servers, and we\u2019ll store related details in a SQLite local database using Prisma. For the user interface and the server-side logic, we\u2019ll use Next.js and some NPM packages to make our work easier.<\/p>\n<h3>AWS and S3 Integration<\/h3>\n<p>To further enhance our image storage capabilities, we can also integrate AWS S3. Here\u2019s how:<\/p>\n<ul>\n<li>\n<p><strong>Set up an AWS account.<\/strong> Before you can use AWS services, you need to set up an AWS account.<\/p>\n<\/li>\n<li>\n<p><strong>Create an IAM user.<\/strong> For security reasons, it\u2019s recommended to create an IAM user with the necessary permissions rather than using the root account.<\/p>\n<\/li>\n<li>\n<p><strong>Set up an S3 bucket.<\/strong> AWS S3 provides scalable object storage. Create an S3 bucket where you\u2019ll store the uploaded images.<\/p>\n<\/li>\n<li>\n<p><strong>Update your Prisma schema.<\/strong>  Modify your Prisma schema to store the image\u2019s S3 bucket path.<\/p>\n<\/li>\n<li>\n<p><strong>Build the image upload component.<\/strong> This component will allow users to select and upload images.<\/p>\n<\/li>\n<li>\n<p><strong>Build the image upload service.<\/strong> This service will handle the backend logic for uploading images to S3.<\/p>\n<\/li>\n<li>\n<p><strong>Integrate the component and service.<\/strong> Finally, integrate the component and service into your application to allow users to upload images to S3.<\/p>\n<\/li>\n<\/ul>\n<p>It\u2019s worth noting that while Cloudinary is excellent for image management, it\u2019s a best practice to store images in blob storage, like AWS S3, rather than directly in the database. By using S3, you can store the image and then save the image\u2019s S3 bucket path in your database, be it SQLite, MySQL, PostgreSQL, or another database of your choice.<\/p>\n<p>If you want to see the app live, here\u2019s a working CodeSandbox (use the \u2018Open Editor\u2019 link in the sandbox tool to jump in):<\/p>\n<iframe \n  src=\"https:\/\/codesandbox.io\/s\/prisma-upload-image-cc5m3?fontsize=14&#038;hidenavigation=1&#038;theme=dark\" style=\"width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;\"title=\"\" allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\" sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"><\/iframe>\n<p>Or you can go to <a href=\"https:\/\/prisma-upload-image.vercel.app\">https:\/\/prisma-upload-image.vercel.app<\/a>.<\/p>\n<p>If you want to see and edit the code of the app, you can clone\n<a href=\"https:\/\/github.com\/fgiuliani\/prisma-upload-image\">https:\/\/github.com\/fgiuliani\/prisma-upload-image<\/a><\/p>\n<h2>Setting Up the Prisma Image Upload Process<\/h2>\n<p>To run the app locally, you\u2019ll need Node.js installed on your computer and a Cloudinary account.<\/p>\n<p>After cloning the repository, replace the values of environment variables present in <em>.env.local<\/em> file:<\/p>\n<ul>\n<li>\n<strong>CLOUD_NAME<\/strong>\n<\/li>\n<li>\n<strong>API_KEY<\/strong>\n<\/li>\n<li>\n<strong>API_SECRET<\/strong>\n<\/li>\n<\/ul>\n<p>You can find the three values at the top left corner of your <a href=\"https:\/\/cloudinary.com\/users\/login\">Cloudinary Dashboard page<\/a>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1764204546\/blog-Upload_Store_and_Display_Images_Using_Prisma-1.png\" alt=\"Image showing screenshot of Cloudinary dashboard as part of the Prisma image upload process\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1232\" height=\"470\"\/><\/p>\n<ul>\n<li>\n<p><strong>DATABASE_PROVIDER.<\/strong> The database provider we want Prisma to connect and use. For this example, we\u2019ll use a SQLite local database. You can use a MySQL or PostgreSQL database if you want, too.<\/p>\n<\/li>\n<li>\n<p><strong>DATABASE_URL.<\/strong> The URL of the database you\u2019ll use.<\/p>\n<\/li>\n<li>\n<p><strong>SERVER_PATH.<\/strong> The root path of your application. This is needed to support Next.js API routes.<\/p>\n<\/li>\n<\/ul>\n<p>You\u2019ll also need to use the Terminal to run <em>npm install<\/em> in the directory where the code of the app lives, so all the involved NPM packages are downloaded and installed.<\/p>\n<p>The repository already contains a SQLite database file with the schema used by Prisma to handle the data and generate the queries. If you edit or add models in <em>schema.prisma<\/em> file, you\u2019ll need to run <em>npx prisma db push \u2013preview-feature<\/em> in the Terminal in order to sync the database with the Prisma schema.<\/p>\n<p>To run the app, go to the Terminal and run <em>npm run dev<\/em>.<\/p>\n<h2>Prisma Image Upload Using Cloudinary<\/h2>\n<p>Let\u2019s see how the app optimizes and uploads images using Cloudinary in  <em>utils\/cloudinary.js<\/em><\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">const<\/span> cloudinary = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"cloudinary\"<\/span>).v2;\n\ncloudinary.config({\n  <span class=\"hljs-attr\">cloud_name<\/span>: process.env.CLOUD_NAME,\n  <span class=\"hljs-attr\">api_key<\/span>: process.env.API_KEY,\n  <span class=\"hljs-attr\">api_secret<\/span>: process.env.API_SECRET\n});\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">uploadImage<\/span>(<span class=\"hljs-params\">imageUploaded<\/span>) <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Promise<\/span>(<span class=\"hljs-function\">(<span class=\"hljs-params\">resolve, reject<\/span>) =&gt;<\/span> {\n    cloudinary.uploader.upload(\n      imageUploaded,\n      { <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">400<\/span>, <span class=\"hljs-attr\">height<\/span>: <span class=\"hljs-number\">300<\/span>, <span class=\"hljs-attr\">crop<\/span>: <span class=\"hljs-string\">\"fill\"<\/span> },\n      (err, res) =&gt; {\n        <span class=\"hljs-keyword\">if<\/span> (err) reject(err);\n        resolve(res);\n      }\n    );\n  });\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<ol>\n<li>We\u2019ll configure the API Key, Secret, and Cloud Name for the Cloudinary integration.<\/li>\n<li>We\u2019ll call the Cloudinary Uploader <em>upload<\/em> method.<\/li>\n<li>The first parameter of the method is the image we want to upload. <a href=\"https:\/\/cloudinary.com\/documentation\/image_upload_api_reference\">cloudinary.uploader.upload<\/a> method can receive the image in different ways: using local file path, the image data (byte array buffer), the data URI, a remote address, or a private storage bucket URL.<\/li>\n<li>The second parameter is an <em>options<\/em> object. We\u2019ll use it to define some options and modify the image before uploading it to Cloudinary\u2019s servers.<\/li>\n<\/ol>\n<h2>How to Use Prisma Store Images: Store and Retrieve Data Using Prisma<\/h2>\n<p>As we\u2019ve defined a schema for the database, we can now use Prisma Client to build queries in a simple way.\nWe\u2019ll instantiate the client in <em>utils\/prisma.js<\/em>.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { PrismaClient } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@prisma\/client\"<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> prisma = <span class=\"hljs-keyword\">new<\/span> PrismaClient();\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> prisma;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We\u2019ll use it to save information in the database, in <em>pages\/api\/upload.js<\/em>.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { getImage } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/..\/utils\/formidable\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { uploadImage } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/..\/utils\/cloudinary\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> prisma <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/..\/utils\/prisma\"<\/span>;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> config = {\n  <span class=\"hljs-attr\">api<\/span>: {\n    <span class=\"hljs-attr\">bodyParser<\/span>: <span class=\"hljs-literal\">false<\/span>,\n  },\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">handle<\/span>(<span class=\"hljs-params\">req, res<\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> imageUploaded = <span class=\"hljs-keyword\">await<\/span> getImage(req);\n\n  <span class=\"hljs-keyword\">const<\/span> imageData = <span class=\"hljs-keyword\">await<\/span> uploadImage(imageUploaded.path);\n\n  <span class=\"hljs-keyword\">const<\/span> result = <span class=\"hljs-keyword\">await<\/span> prisma.image.create({\n    <span class=\"hljs-attr\">data<\/span>: {\n      <span class=\"hljs-attr\">publicId<\/span>: imageData.public_id,\n      <span class=\"hljs-attr\">format<\/span>: imageData.format,\n      <span class=\"hljs-attr\">version<\/span>: imageData.version.toString(),\n    },\n  });\n\n  res.json(result);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We\u2019ll create an image with details extracted from the Cloudinary upload response. Then, we\u2019ll use those details later to conform the image public URL and display it in the gallery page.<\/p>\n<p>Another cool package that we\u2019re using in the app is <em>formidable<\/em>, which helps us handle the form submitted by the user when uploading the image, so we can generate an image buffer to be sent through the Cloudinary API. We\u2019ll extract an image buffer from the form data in <em>utils\/formidable.js<\/em><\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { IncomingForm } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"formidable\"<\/span>;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getImage<\/span>(<span class=\"hljs-params\">formData<\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> data = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Promise<\/span>(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">resolve, reject<\/span>) <\/span>{\n    <span class=\"hljs-keyword\">const<\/span> form = <span class=\"hljs-keyword\">new<\/span> IncomingForm({ <span class=\"hljs-attr\">keepExtensions<\/span>: <span class=\"hljs-literal\">true<\/span> });\n    form.parse(formData, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">err, fields, files<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">if<\/span> (err) <span class=\"hljs-keyword\">return<\/span> reject(err);\n      resolve({ fields, files });\n    });\n  });\n\n  <span class=\"hljs-keyword\">return<\/span> data.files.image;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We can also see how we\u2019ll handle image uploads in the page, using an <code>&lt;input&gt;<\/code> HTML element, in <em>pages\/upload.jsx<\/em><\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> React, { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> Layout <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/Layout\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> Router <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/router\"<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> Upload = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">const<\/span> &#91;imageUploaded, setImageUploaded] = useState();\n\n  <span class=\"hljs-keyword\">const<\/span> handleChange = <span class=\"hljs-function\">(<span class=\"hljs-params\">event<\/span>) =&gt;<\/span> {\n    setImageUploaded(event.target.files&#91;<span class=\"hljs-number\">0<\/span>]);\n  };\n\n  <span class=\"hljs-keyword\">const<\/span> submitData = <span class=\"hljs-keyword\">async<\/span> (e) =&gt; {\n    e.preventDefault();\n\n    <span class=\"hljs-keyword\">if<\/span> (!imageUploaded) {\n      <span class=\"hljs-keyword\">return<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">try<\/span> {\n      <span class=\"hljs-keyword\">const<\/span> formData = <span class=\"hljs-keyword\">new<\/span> FormData();\n      formData.append(<span class=\"hljs-string\">\"image\"<\/span>, imageUploaded);\n\n      <span class=\"hljs-keyword\">await<\/span> fetch(<span class=\"hljs-string\">\"\/api\/upload\"<\/span>, {\n        <span class=\"hljs-attr\">method<\/span>: <span class=\"hljs-string\">\"POST\"<\/span>,\n        <span class=\"hljs-attr\">body<\/span>: formData\n      });\n\n      Router.push(<span class=\"hljs-string\">\"\/\"<\/span>);\n    } <span class=\"hljs-keyword\">catch<\/span> (error) {\n      <span class=\"hljs-built_in\">console<\/span>.error(error);\n    }\n  };\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"page\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">onSubmit<\/span>=<span class=\"hljs-string\">{submitData}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Upload Image<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span>\n            <span class=\"hljs-attr\">onChange<\/span>=<span class=\"hljs-string\">{handleChange}<\/span>\n            <span class=\"hljs-attr\">accept<\/span>=<span class=\"hljs-string\">\".jpg, .png, .gif, .jpeg\"<\/span>\n            <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"file\"<\/span>\n          &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">input<\/span>&gt;<\/span>\n\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"Upload\"<\/span> <span class=\"hljs-attr\">disabled<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">style<\/span> <span class=\"hljs-attr\">jsx<\/span>&gt;<\/span>{`\n        .page {\n          background: white;\n          padding: 3rem;\n          display: flex;\n          justify-content: center;\n          align-items: center;\n        }\n\n        input&#91;type=\"submit\"] {\n          background: #ececec;\n          border: 0;\n          padding: 1rem 2rem;\n        }\n      `}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">style<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Layout<\/span>&gt;<\/span><\/span>\n  );\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Upload; \n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<ol>\n<li>We\u2019ll limit the allowed file formats that our <code>&lt;input&gt;<\/code> element will support to only accept image files.<\/li>\n<li>Whenever the <code>&lt;input&gt;<\/code> changes its value, we\u2019ll update the state of <em>imageUploaded<\/em> to contain the most recent file uploaded details.<\/li>\n<li>After clicking Submit, we\u2019ll create a <em>FormData<\/em> object and include the uploaded image.<\/li>\n<li>We\u2019ll send that object as a parameter when we call the <em>pages\/api\/upload.js<\/em> API route.<\/li>\n<\/ol>\n<p>In <em>pages\/api\/images.js<\/em> we\u2019ll retrieve all the image records stored in the database.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> prisma <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/..\/utils\/prisma\"<\/span>;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">handle<\/span>(<span class=\"hljs-params\">req, res<\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> images = <span class=\"hljs-keyword\">await<\/span> prisma.image.findMany();\n  res.json(images);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Next, we\u2019ll can generate an <code>*&lt;img&gt;*<\/code> HTML element for each image in <em>pages\/index.jsx<\/em><\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> Layout <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/Layout\"<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> Gallery = <span class=\"hljs-function\">(<span class=\"hljs-params\">props<\/span>) =&gt;<\/span> {\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"page\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Image Gallery<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n          {props.images.map((image) =&gt; (\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n              <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{<\/span>`<span class=\"hljs-attr\">https:<\/span>\/\/<span class=\"hljs-attr\">res.cloudinary.com<\/span>\/${<span class=\"hljs-attr\">process.env.CLOUD_NAME<\/span>}\/<span class=\"hljs-attr\">v<\/span>${<span class=\"hljs-attr\">image.version<\/span>}\/${<span class=\"hljs-attr\">image.publicId<\/span>}<span class=\"hljs-attr\">.<\/span>${<span class=\"hljs-attr\">image.format<\/span>}`}\n              <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{image.publicId}<\/span>\n            \/&gt;<\/span>\n          ))}\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">style<\/span> <span class=\"hljs-attr\">jsx<\/span>&gt;<\/span>{`\n        .image {\n          background: white;\n          transition: box-shadow 0.1s ease-in;\n        }\n\n        .image:hover {\n          box-shadow: 1px 1px 3px #aaa;\n        }\n\n        .image + .image {\n          margin-top: 2rem;\n        }\n      `}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">style<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Layout<\/span>&gt;<\/span><\/span>\n  );\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> getServerSideProps = <span class=\"hljs-keyword\">async<\/span> () =&gt; {\n  <span class=\"hljs-keyword\">const<\/span> res = <span class=\"hljs-keyword\">await<\/span> fetch(<span class=\"hljs-string\">`<span class=\"hljs-subst\">${process.env.SERVER_PATH}<\/span>\/api\/images`<\/span>);\n  <span class=\"hljs-keyword\">const<\/span> images = <span class=\"hljs-keyword\">await<\/span> res.json();\n  <span class=\"hljs-keyword\">return<\/span> {\n    <span class=\"hljs-attr\">props<\/span>: { images },\n  };\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Gallery;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h2>Summary<\/h2>\n<p>With this image gallery app, we learned how to upload images to Cloudinary using its Node.js SDK, how to display images stored in Cloudinary servers, and how to store details related to them in a database using Prisma ORM. This example app can be used and extended for more advanced and complex use cases, to add other models to the Prisma schema, or to manipulate the files stored in Cloudinary.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":87,"featured_media":29115,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,370],"class_list":["post-28286","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-image"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Upload, Store, and Display Images Using Prisma<\/title>\n<meta name=\"description\" content=\"The Prisma upload file process made simple: learn how to use Prisma and Cloudinary to upload, store, and manage images in your web app for free\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Upload, Store, and Display Images Using Prisma\" \/>\n<meta property=\"og:description\" content=\"The Prisma upload file process made simple: learn how to use Prisma and Cloudinary to upload, store, and manage images in your web app for free\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-05-22T14:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-27T00:49:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"melindapham\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"Upload, Store, and Display Images Using Prisma\",\"datePublished\":\"2023-05-22T14:00:00+00:00\",\"dateModified\":\"2025-11-27T00:49:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma\"},\"wordCount\":7,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"Image\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2023\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma\",\"url\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma\",\"name\":\"Upload, Store, and Display Images Using Prisma\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA\",\"datePublished\":\"2023-05-22T14:00:00+00:00\",\"dateModified\":\"2025-11-27T00:49:48+00:00\",\"description\":\"The Prisma upload file process made simple: learn how to use Prisma and Cloudinary to upload, store, and manage images in your web app for free\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA\",\"width\":2000,\"height\":1100,\"caption\":\"Image showing graphic representation of prisma store images with screenshot of code denoting prisma image upload\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Upload, Store, and Display Images Using Prisma\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\",\"name\":\"melindapham\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"caption\":\"melindapham\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Upload, Store, and Display Images Using Prisma","description":"The Prisma upload file process made simple: learn how to use Prisma and Cloudinary to upload, store, and manage images in your web app for free","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma","og_locale":"en_US","og_type":"article","og_title":"Upload, Store, and Display Images Using Prisma","og_description":"The Prisma upload file process made simple: learn how to use Prisma and Cloudinary to upload, store, and manage images in your web app for free","og_url":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma","og_site_name":"Cloudinary Blog","article_published_time":"2023-05-22T14:00:00+00:00","article_modified_time":"2025-11-27T00:49:48+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA","type":"image\/jpeg"}],"author":"melindapham","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"Upload, Store, and Display Images Using Prisma","datePublished":"2023-05-22T14:00:00+00:00","dateModified":"2025-11-27T00:49:48+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma"},"wordCount":7,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA","keywords":["Guest Post","Image"],"inLanguage":"en-US","copyrightYear":"2023","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma","url":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma","name":"Upload, Store, and Display Images Using Prisma","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA","datePublished":"2023-05-22T14:00:00+00:00","dateModified":"2025-11-27T00:49:48+00:00","description":"The Prisma upload file process made simple: learn how to use Prisma and Cloudinary to upload, store, and manage images in your web app for free","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA","width":2000,"height":1100,"caption":"Image showing graphic representation of prisma store images with screenshot of code denoting prisma image upload"},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/upload-and-display-images-using-prisma#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Upload, Store, and Display Images Using Prisma"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9","name":"melindapham","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","caption":"melindapham"}}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1684271256\/Blog-upload_and_display_images_with_Prisma\/Blog-upload_and_display_images_with_Prisma.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28286","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28286"}],"version-history":[{"count":15,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28286\/revisions"}],"predecessor-version":[{"id":39428,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28286\/revisions\/39428"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/29115"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28286"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28286"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28286"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}