<?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: Victor Moni</title>
    <description>The latest articles on DEV Community by Victor Moni (@victormoni).</description>
    <link>https://dev.to/victormoni</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%2F3268790%2F4033fd3f-15c8-4c18-862a-03fb619ef882.png</url>
      <title>DEV Community: Victor Moni</title>
      <link>https://dev.to/victormoni</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/victormoni"/>
    <language>en</language>
    <item>
      <title>Making Image Delivery Visible with Next.js and Cloudinary</title>
      <dc:creator>Victor Moni</dc:creator>
      <pubDate>Tue, 27 Oct 2026 18:45:10 +0000</pubDate>
      <link>https://dev.to/victormoni/making-image-delivery-visible-with-nextjs-and-cloudinary-2nml</link>
      <guid>https://dev.to/victormoni/making-image-delivery-visible-with-nextjs-and-cloudinary-2nml</guid>
      <description>&lt;p&gt;After completing &lt;strong&gt;Cloud to Crowd: Media IQ for Developers with Next.js&lt;/strong&gt;, I wanted a practical way to explore image delivery. With Codex assistance, I built &lt;strong&gt;Media Lab&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://media-lab-cloudinary.vercel.app/" rel="noopener noreferrer"&gt;Try the live demo&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://github.com/VictorMoni/media-lab-cloudinary" rel="noopener noreferrer"&gt;Explore the source code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The same image can appear in a card, a gallery, or a portrait layout. Delivering the original file in every context deserves a closer look: the dimensions and crop each interface needs can be different.&lt;/p&gt;

&lt;p&gt;Media Lab explores this problem through a small Next.js learning project built with Codex assistance. Its purpose is to make image delivery decisions visible by letting you switch between an original image URL and a Cloudinary transformation URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvv0obycp9hn633w9sgi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvv0obycp9hn633w9sgi.png" alt="Media Lab on Vercel showing the portrait crop controls and a transformed flower image" width="498" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The actual deployed application, with Portrait selected.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A small, observable experiment
&lt;/h2&gt;

&lt;p&gt;The lab includes a gallery of four public Cloudinary sample images. Select an image, switch between landscape, square, and portrait crops, choose a delivery width, and inspect the resulting URL.&lt;/p&gt;

&lt;p&gt;A separate form lets you try a public image from another Cloudinary cloud by entering a cloud name and Public ID. It does not upload files or require an API secret. The asset must be publicly accessible and allow the requested transformations.&lt;/p&gt;

&lt;p&gt;The project is a learning experiment rather than a production storefront or client engagement.&lt;/p&gt;

&lt;h2&gt;
  
  
  The transformation is in the URL
&lt;/h2&gt;

&lt;p&gt;A landscape variant with a delivery width of 640 pixels uses this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://res.cloudinary.com/demo/image/upload/c_fill,g_auto,w_640,h_427/q_auto/f_auto/sample
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each part represents a delivery decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;c_fill&lt;/code&gt; fills the requested dimensions, cropping when necessary.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;g_auto&lt;/code&gt; uses automatic gravity to guide the crop.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;w_640,h_427&lt;/code&gt; defines the dimensions of the variant.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;q_auto&lt;/code&gt; adjusts quality automatically.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;f_auto&lt;/code&gt; negotiates an appropriate format based on the requesting browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quality and format use separate URL components, as described in the &lt;a href="https://cloudinary.com/documentation/image_optimization" rel="noopener noreferrer"&gt;Cloudinary image optimization documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Original mode, the URL includes none of these transformations. CSS still controls its displayed size, so the space an image occupies on the page should not be confused with the dimensions of the delivered file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdemo%2Fimage%2Fupload%2Fc_fill%2Cg_auto%2Cw_640%2Ch_427%2Fq_auto%2Ff_auto%2Fsample" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdemo%2Fimage%2Fupload%2Fc_fill%2Cg_auto%2Cw_640%2Ch_427%2Fq_auto%2Ff_auto%2Fsample" alt="Cloudinary flower sample delivered as a 640 by 427 pixel landscape crop" width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A landscape variant of the same sample asset. Image source: Cloudinary demo cloud.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Centralizing delivery decisions
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;lib/cloudinary.mjs&lt;/code&gt; module builds image URLs and limits delivery widths to five options: 320, 480, 640, 960, and 1280 pixels. This avoids generating an unlimited number of variants for every small interface adjustment.&lt;/p&gt;

&lt;p&gt;The function also encodes Public ID segments while preserving folder separators and validates the cloud name before assembling a URL.&lt;/p&gt;

&lt;p&gt;Here is an example from the project:&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;imageUrl&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;cloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;demo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;publicId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sample&lt;/span&gt;&lt;span class="dl"&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;640&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;portrait&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This requests a 640 × 800 pixel variant with automatic crop positioning, quality, and format selection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsive delivery and comparison serve different purposes
&lt;/h2&gt;

&lt;p&gt;The comparison panel requests a fixed width. This makes it possible to inspect a particular variant and see how each setting changes the URL.&lt;/p&gt;

&lt;p&gt;The gallery cards use &lt;code&gt;srcSet&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; instead. The browser receives several width candidates and selects one based on the available display space and pixel density.&lt;/p&gt;

&lt;p&gt;Images are delivered directly from Cloudinary through &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; elements, without an additional Next.js image optimization layer. Alternative text, lazy loading in the gallery, and image error messages complete the basic experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdemo%2Fimage%2Fupload%2Fc_fill%2Cg_auto%2Cw_640%2Ch_640%2Fq_auto%2Ff_auto%2Fcld-sample-2" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdemo%2Fimage%2Fupload%2Fc_fill%2Cg_auto%2Cw_640%2Ch_640%2Fq_auto%2Ff_auto%2Fcld-sample-2" alt="Mountain sample delivered as a square crop" width="640" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A square variant of another gallery asset. Image source: Cloudinary demo cloud.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What was checked
&lt;/h2&gt;

&lt;p&gt;During assisted development, Codex ran five automated tests covering URL generation and completed a production build successfully. Browser checks confirmed that the four sample images loaded and that switching to a portrait crop or the original version updated the URL and displayed dimension information.&lt;/p&gt;

&lt;p&gt;These checks cover parts of the implementation. They do not establish a performance improvement in a production application or prove that every crop is appropriate on every device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring the next step
&lt;/h2&gt;

&lt;p&gt;The lab does not display estimated savings percentages. To report quantitative results, open the browser Network tab, disable caching, and record the transferred size and actual response format for each variant.&lt;/p&gt;

&lt;p&gt;Record the image dimensions too. Comparing a large original with a small cropped variant measures the combined effects of resizing, cropping, and optimization. Attributing the entire difference to compression would be misleading.&lt;/p&gt;

&lt;p&gt;Response times need similar care. Network conditions, caching, and the first generation of a transformation can affect a measurement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making image delivery decisions visible
&lt;/h2&gt;

&lt;p&gt;Working with media involves decisions about interface design, dimensions, cropping, and delivery. This example brings those decisions into a small interactive page, with URLs that can be inspected and opened separately.&lt;/p&gt;

&lt;p&gt;The next step is to try original assets, evaluate the crops, and record reproducible measurements. That provides a foundation for a more personal account of the choices made and the results observed while using the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloudinary.com/documentation/image_transformations" rel="noopener noreferrer"&gt;Cloudinary image transformations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloudinary.com/documentation/image_optimization" rel="noopener noreferrer"&gt;Cloudinary image optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/app/getting-started/installation" rel="noopener noreferrer"&gt;Next.js installation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://media-lab-cloudinary.vercel.app/" rel="noopener noreferrer"&gt;Open Media Lab&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://github.com/VictorMoni/media-lab-cloudinary" rel="noopener noreferrer"&gt;View the GitHub repository&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By Victor Moni. Project and article developed with Codex assistance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cloudinary</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
