<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bandesha</title>
    <description>The latest articles on DEV Community by Bandesha (@ahmad_jawad_45f5111ef77b4).</description>
    <link>https://dev.to/ahmad_jawad_45f5111ef77b4</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4227317%2F3ba3729a-9d99-45c0-a30b-bd8ea70d5774.jpg</url>
      <title>DEV Community: Bandesha</title>
      <link>https://dev.to/ahmad_jawad_45f5111ef77b4</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmad_jawad_45f5111ef77b4"/>
    <language>en</language>
    <item>
      <title>Building CPGIE: A Cloudinary-Powered Photo Gallery and Image Editor</title>
      <dc:creator>Bandesha</dc:creator>
      <pubDate>Wed, 04 Nov 2026 23:04:24 +0000</pubDate>
      <link>https://dev.to/ahmad_jawad_45f5111ef77b4/building-cpgie-a-cloudinary-powered-photo-gallery-and-image-editor-4pef</link>
      <guid>https://dev.to/ahmad_jawad_45f5111ef77b4/building-cpgie-a-cloudinary-powered-photo-gallery-and-image-editor-4pef</guid>
      <description>&lt;p&gt;Modern applications need more than basic image uploads. A single photograph may require a square version for Instagram, a wide crop for a website banner, an optimized copy for mobile devices, and a watermark for ownership.&lt;/p&gt;

&lt;p&gt;Creating and storing every variation manually wastes time and storage. That is why I built &lt;strong&gt;Cloudinary Photo Gallery &amp;amp; Image Editor (CPGIE)&lt;/strong&gt;, a browser-based image management and transformation studio powered by Cloudinary.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Developers and content creators regularly face several media-management challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large images slow down websites.&lt;/li&gt;
&lt;li&gt;Standard cropping can remove faces or important details.&lt;/li&gt;
&lt;li&gt;Different social platforms require different dimensions.&lt;/li&gt;
&lt;li&gt;Permanent watermarks modify the original image.&lt;/li&gt;
&lt;li&gt;Image-processing libraries require additional server resources.&lt;/li&gt;
&lt;li&gt;API credentials must remain secure on the backend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted to create one application where users could upload, organize, transform, and share images without permanently changing the original assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing CPGIE
&lt;/h2&gt;

&lt;p&gt;CPGIE combines a cloud image gallery with an interactive editor. Users can upload an image and immediately generate transformed versions through Cloudinary.&lt;/p&gt;

&lt;p&gt;The project includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drag-and-drop image uploads&lt;/li&gt;
&lt;li&gt;A responsive image gallery&lt;/li&gt;
&lt;li&gt;Image resizing and cropping&lt;/li&gt;
&lt;li&gt;Rotation and quality controls&lt;/li&gt;
&lt;li&gt;Grayscale, sepia, blur, sharpen, oil-paint, cartoon, and pixel effects&lt;/li&gt;
&lt;li&gt;Face-aware smart cropping&lt;/li&gt;
&lt;li&gt;Dynamic text watermarks&lt;/li&gt;
&lt;li&gt;Custom frames and borders&lt;/li&gt;
&lt;li&gt;Social-media image presets&lt;/li&gt;
&lt;li&gt;Image metadata and gallery statistics&lt;/li&gt;
&lt;li&gt;Downloadable and shareable transformation URLs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cloudinary stores the original asset while transformations are generated dynamically. This means users can create several versions of one image without storing duplicate files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;HTML, CSS, and JavaScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Node.js and Express&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upload handling&lt;/td&gt;
&lt;td&gt;Multer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Media management&lt;/td&gt;
&lt;td&gt;Cloudinary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Vercel&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The frontend provides the gallery and editor interface. The Express backend handles operations that require secure Cloudinary credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secure Image Uploads
&lt;/h2&gt;

&lt;p&gt;Cloudinary API secrets should never be included in frontend JavaScript. CPGIE sends images to an Express endpoint, which streams them securely to Cloudinary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;memoryStorage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fileSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;uploadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upload_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;resource_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;photo-gallery&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser receives only safe information, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public asset ID&lt;/li&gt;
&lt;li&gt;Secure delivery URL&lt;/li&gt;
&lt;li&gt;Image dimensions&lt;/li&gt;
&lt;li&gt;File size&lt;/li&gt;
&lt;li&gt;Image format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Cloudinary API secret remains in server environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Transformations
&lt;/h2&gt;

&lt;p&gt;One of Cloudinary’s most useful features is URL-based image transformation.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transformedUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;crop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fill&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;improve&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fetch_format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This transformation resizes and crops the image, improves its appearance, optimizes its quality, and selects a suitable format for the browser.&lt;/p&gt;

&lt;p&gt;CPGIE allows users to configure these transformations visually instead of manually writing URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image Effects
&lt;/h2&gt;

&lt;p&gt;The editor includes several one-click effects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grayscale&lt;/li&gt;
&lt;li&gt;Sepia&lt;/li&gt;
&lt;li&gt;Blur&lt;/li&gt;
&lt;li&gt;Sharpen&lt;/li&gt;
&lt;li&gt;Oil paint&lt;/li&gt;
&lt;li&gt;Cartoonify&lt;/li&gt;
&lt;li&gt;Pixelate&lt;/li&gt;
&lt;li&gt;Vignette&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When an effect is selected, the application generates a new Cloudinary delivery URL and displays the result in the editor.&lt;/p&gt;

&lt;p&gt;The original uploaded image remains unchanged.&lt;/p&gt;

&lt;h2&gt;
  
  
  Face-Aware Smart Cropping
&lt;/h2&gt;

&lt;p&gt;Regular center cropping can remove a person’s face from profile pictures and thumbnails.&lt;/p&gt;

&lt;p&gt;CPGIE includes a smart-crop tool using Cloudinary’s face gravity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;crop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;thumb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;gravity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;face&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cloudinary detects the face and positions the crop around it. This is useful for avatars, team pages, creator profiles, and portfolio cards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Watermarks
&lt;/h2&gt;

&lt;p&gt;CPGIE can add text watermarks without permanently modifying the original file.&lt;/p&gt;

&lt;p&gt;Users enter their branding or copyright text, and Cloudinary creates an overlay during image delivery.&lt;/p&gt;

&lt;p&gt;Dynamic watermarks offer an important advantage: if the branding changes, a new transformation URL can be generated without editing and re-uploading every original image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Social-Media Presets
&lt;/h2&gt;

&lt;p&gt;Each social platform uses different image dimensions. CPGIE generates optimized Cloudinary URLs for common layouts, including:&lt;/p&gt;

&lt;h3&gt;
  
  
  Instagram
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Square post&lt;/li&gt;
&lt;li&gt;Portrait post&lt;/li&gt;
&lt;li&gt;Story format&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  X/Twitter
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Standard post&lt;/li&gt;
&lt;li&gt;Profile header&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Facebook
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Standard post&lt;/li&gt;
&lt;li&gt;Cover image&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  LinkedIn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Professional post format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, an Instagram square can be generated with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;crop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fill&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users can copy each generated URL or download the transformed image.&lt;/p&gt;

&lt;h2&gt;
  
  
  User Interface
&lt;/h2&gt;

&lt;p&gt;I designed CPGIE as a responsive dashboard with four main sections:&lt;/p&gt;

&lt;h3&gt;
  
  
  Gallery
&lt;/h3&gt;

&lt;p&gt;The gallery displays uploaded Cloudinary assets in a responsive grid. Users can search, sort, and select images for editing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Editor
&lt;/h3&gt;

&lt;p&gt;The editor provides controls for dimensions, effects, rotation, quality, watermarks, downloads, and URL copying.&lt;/p&gt;

&lt;h3&gt;
  
  
  Templates
&lt;/h3&gt;

&lt;p&gt;The templates section creates image variations for different social-media platforms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analytics
&lt;/h3&gt;

&lt;p&gt;The analytics section displays information such as image count, dimensions, recent uploads, and the highest-resolution asset.&lt;/p&gt;

&lt;p&gt;A sidebar provides quick access to uploads, effects, smart cropping, frames, and other tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment on Vercel
&lt;/h2&gt;

&lt;p&gt;The frontend and Express API are deployed under one Vercel domain. This allows the browser to make same-origin requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/upload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/images&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/transform&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cloudinary credentials are configured through Vercel environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLOUDINARY_CLOUD_NAME
CLOUDINARY_API_KEY
CLOUDINARY_API_SECRET
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These values should never be committed to a public repository.&lt;/p&gt;

&lt;p&gt;The project also includes a health endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A correctly configured deployment returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cloudinary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"configured"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Building CPGIE taught me several practical lessons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Streaming uploads are more efficient than converting files to Base64.&lt;/li&gt;
&lt;li&gt;API secrets must remain on the backend.&lt;/li&gt;
&lt;li&gt;Dynamic transformations preserve original assets.&lt;/li&gt;
&lt;li&gt;One source image can support many platforms and layouts.&lt;/li&gt;
&lt;li&gt;Automatic quality and format selection simplify optimization.&lt;/li&gt;
&lt;li&gt;Visual previews make transformation APIs easier to understand.&lt;/li&gt;
&lt;li&gt;Deployment environment variables are as important as application code.&lt;/li&gt;
&lt;li&gt;Clear server errors make production debugging much easier.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;CPGIE started as a simple image uploader and developed into a complete Cloudinary-powered media workspace.&lt;/p&gt;

&lt;p&gt;It demonstrates secure uploads, responsive galleries, dynamic transformations, face-aware cropping, watermarks, social-media presets, and cloud-based delivery in one full-stack project.&lt;/p&gt;

&lt;p&gt;The application is useful for photographers, developers, marketers, and content creators who need a faster way to prepare images for different platforms.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href="https://cpgie-7cw3.vercel.app" rel="noopener noreferrer"&gt;https://cpgie-7cw3.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/ahmadjawad-533/CPGIE" rel="noopener noreferrer"&gt;https://github.com/ahmadjawad-533/CPGIE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built for the &lt;strong&gt;Cloudinary Creator Community&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
