{"id":35303,"date":"2024-08-19T07:00:00","date_gmt":"2024-08-19T14:00:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=35303"},"modified":"2024-08-19T09:38:52","modified_gmt":"2024-08-19T16:38:52","slug":"optimize-visuals-composable-next-js-e-commerce-website","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website","title":{"rendered":"Optimize Your Visuals on a Composable Next.js E-commerce Website"},"content":{"rendered":"\n<p>In a composable website, functionality is broken down into independent components, allowing for better flexibility and scalability. This modular approach changes how websites are designed, developed, and maintained. By embracing composability, you build robust and adaptable systems that meet modern standards.<\/p>\n\n\n\n<p>In this post, you\u2019ll see how Cloudinary comfortably fits into the composable architecture by building a simple e-commerce store that serves and renders images from different sources using the <a target=\"_blank\" href=\"https:\/\/cloudinary.com\/documentation\/fetch_remote_images#overview\" rel=\"noreferrer noopener\">Cloudinary<\/a><a target=\"_blank\" href=\"https:\/\/cloudinary.com\/documentation\/fetch_remote_images#overview\" rel=\"noreferrer noopener\"> fetch feature<\/a>. Cloudinary takes care of fetching the image, applying optimizations on the fly, and delivering it.<\/p>\n\n\n\n<p>To follow along, you should know TypeScript or JavaScript on a basic level and have a <a target=\"_blank\" href=\"https:\/\/cloudinary.com\/users\/register_free\" rel=\"noreferrer noopener\">Cloudinary account<\/a> (it\u2019s free!).&nbsp;<\/p>\n\n\n\n<p>The completed app is in this <a target=\"_blank\" href=\"https:\/\/github.com\/folucode\/cloudinary-composable-ecommerce\" rel=\"noreferrer noopener\">GitHub Repository<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Set Up a Next.js App<\/h2>\n\n\n\n<p>Run the command below to set up a Next.js app with any name you wish:<\/p>\n\n\n\n<p><code>$ npx create-next-app@latest &lt;APPLICATION-NAME&gt;<\/code><\/p>\n\n\n\n<p>Select the options below in the process of setting up the app, or modify as you see fit:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"1024\" height=\"171\" data-public-id=\"Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1.png\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_1024,h_171,c_scale\/f_auto,q_auto\/v1724085355\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1.png?_i=AA\" alt=\"\" class=\"wp-post-35303 wp-image-35304\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1724085355\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724085355\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1.png?_i=AA 1159w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724085355\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1.png?_i=AA 300w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724085355\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1.png?_i=AA 768w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724085355\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-1.png?_i=AA 1024w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Install the Cloudinary package with the command below:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">$ npm i cloudinary<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Style the Application<\/h2>\n\n\n\n<p>Now that the app is set up, you can add some basic styles with the code below to make it more appealing. First, change the directory into the application by navigating to the page.module.css file and replace the boilerplate code with the code below:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-comment\">\/\/ src\/app\/page.module.css<\/span>\n\n.main {\n  <span class=\"hljs-attr\">display<\/span>: flex;\n  flex-direction: column;\n  justify-content: space-evenly;\n  width: <span class=\"hljs-number\">100<\/span>vw;\n  height: <span class=\"hljs-number\">100<\/span>vh;\n  align-items: center;\n}\n.product-area {\n  <span class=\"hljs-attr\">display<\/span>: flex;\n  flex-direction: row;\n  justify-content: space-evenly;\n  width: <span class=\"hljs-number\">800<\/span>px;\n  flex-wrap: wrap;\n  margin-top: <span class=\"hljs-number\">2<\/span>rem;\n}\n.main &gt; h1 {\n  <span class=\"hljs-attr\">margin<\/span>: <span class=\"hljs-number\">3<\/span>rem <span class=\"hljs-number\">0<\/span>;\n}\n.card {\n  <span class=\"hljs-attr\">padding<\/span>: <span class=\"hljs-number\">1<\/span>rem;\n  margin: <span class=\"hljs-number\">0.2<\/span>rem;\n  width: <span class=\"hljs-number\">350<\/span>px;\n  border-radius: <span class=\"hljs-keyword\">var<\/span>(--border-radius);\n  background: rgba(<span class=\"hljs-keyword\">var<\/span>(--card-rgb), <span class=\"hljs-number\">0<\/span>);\n  border: <span class=\"hljs-number\">1<\/span>px solid rgba(<span class=\"hljs-keyword\">var<\/span>(--card-border-rgb), <span class=\"hljs-number\">0.15<\/span>);\n}\n.card span {\n  <span class=\"hljs-attr\">display<\/span>: inline-block;\n  transition: transform <span class=\"hljs-number\">200<\/span>ms;\n}\n.card h2 {\n  font-weight: <span class=\"hljs-number\">600<\/span>;\n  margin-bottom: <span class=\"hljs-number\">0.7<\/span>rem;\n}\n.card p {\n  <span class=\"hljs-attr\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n  opacity: <span class=\"hljs-number\">0.6<\/span>;\n  font-size: <span class=\"hljs-number\">0.9<\/span>rem;\n  line-height: <span class=\"hljs-number\">1.5<\/span>;\n  max-width: <span class=\"hljs-number\">30<\/span>ch;\n  text-wrap: balance;\n}\n.img {\n  <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">100<\/span>%;\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\n\n<p>Next, in the <code>page.tsx<\/code> file, replace the boilerplate code with the code below. This code snippet is the app&#8217;s foundation. Later, you\u2019ll add image cards that display the images served and optimized by Cloudinary fetch.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-comment\">\/\/\/ src\/app\/page.tsx<\/span>\n\n<span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/page.module.css'<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> Home: React.FC = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.main}<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>My Pet Store!<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/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\">{styles&#91;<\/span>'<span class=\"hljs-attr\">product-area<\/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\">div<\/span>&gt;<\/span><\/span>\n  );\n};\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Home;<\/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\n\n<h2 class=\"wp-block-heading\">Set Up Environment Variables<\/h2>\n\n\n\n<p>Now that all the basic setup is done, you need to add the environment variables that will enable remote access to Cloudinary. To do this, add a new file, <code>.env.local<\/code>, to your project\u2019s root directory and paste the code below in there. This file will house all the Cloudinary app keys you need.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">CLOUDINARY_CLOUD_NAME=<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CLOUDINARY_CLOUD_NAME<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To get your cloud name, navigate to your <a href=\"https:\/\/console.cloudinary.com\/pm\/c-44312a85dae383cdb3fedab809bc64\/developer-dashboard\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary developer dashboard<\/a>,where you\u2019ll see it under the <strong>Product Environment Credentials<\/strong> section.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img width=\"1024\" height=\"207\" data-public-id=\"Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2.png\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/w_1024,h_207,c_scale\/f_auto,q_auto\/v1724085351\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2.png?_i=AA\" alt=\"\" class=\"wp-post-35303 wp-image-35305\" data-format=\"png\" data-transformations=\"f_auto,q_auto\" data-version=\"1724085351\" data-seo=\"1\" srcset=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724085351\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2.png?_i=AA 1600w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724085351\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2.png?_i=AA 300w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724085351\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2.png?_i=AA 768w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724085351\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2.png?_i=AA 1024w, https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1724085351\/Web_Assets\/blog\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2\/blog-Optimize-Your-Visuals-on-a-Composable-Next.js-E-commerce-Website-2.png?_i=AA 1536w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>After this setup, you can now work on the fetch and optimize functionality.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Fetch and Optimize an Image<\/h2>\n\n\n\n<p>To fetch and optimize images, you will first need to set up a reusable image component that will house all the functionality for fetching and applying image transformations to individual images.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Set Up the Image Component<\/h3>\n\n\n\n<p>Add a new folder in the <code>src<\/code> directory and call it components. In the <code>components folder<\/code>, add a new file called <code>image-card.tsx<\/code>. In the <code>image-card.tsx<\/code> file, paste the code below; this code snippet defines a React component, <code>ImageComponent<\/code>, that takes in prop values and constructs the Cloudinary fetch URL using these props to render an image with specified transformations applied.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'..\/app\/page.module.css'<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> cloudinaryFetchUrl = (\n  imageUrl: string,\n  <span class=\"hljs-attr\">transformations<\/span>: string\n): <span class=\"hljs-function\"><span class=\"hljs-params\">string<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">const<\/span> cloudName: string | <span class=\"hljs-literal\">undefined<\/span> = process.env.CLOUDINARY_CLOUD_NAME;\n  <span class=\"hljs-keyword\">const<\/span> encodedImageUrl: string = <span class=\"hljs-built_in\">encodeURIComponent<\/span>(imageUrl);\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`https:\/\/res.cloudinary.com\/<span class=\"hljs-subst\">${cloudName}<\/span>\/image\/fetch\/<span class=\"hljs-subst\">${transformations}<\/span>\/<span class=\"hljs-subst\">${encodedImageUrl}<\/span>`<\/span>;\n};\n\ninterface ImageComponentProps {\n  <span class=\"hljs-attr\">src<\/span>: string;\n  alt: string;\n  transformations: string;\n}\n\n<span class=\"hljs-keyword\">const<\/span> ImageComponent: React.FC&lt;ImageComponentProps&gt; = ({\n  src,\n  alt,\n  transformations,\n}) =&gt; {\n  <span class=\"hljs-keyword\">const<\/span> imageUrl = cloudinaryFetchUrl(src, transformations);\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n      <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.img}<\/span>\n      <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{imageUrl}<\/span>\n      <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">{alt}<\/span>\n    \/&gt;<\/span><\/span>\n  );\n};\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> ImageComponent;\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\n\n<p>In the function, two variables are declared in the cloudinaryFetchUrl function: <code>the cloud_name variable<\/code>, which retrieves the Cloudinary cloud name from environment variables, and <code>encodedImageUrl<\/code>, which encodes the image URL to make it safe.<\/p>\n\n\n\n<p>Next, the <code>ImageComponentProps<\/code> interface defines the props that the <code>ImageComponent<\/code> functional component will accept: <code>src<\/code>, <code>alt<\/code>, and <code>transformations<\/code>. In the <code>ImageComponent<\/code>, the <code>cloudinaryFetchUrl<\/code> function is called with <code>src<\/code> and <code>transformations<\/code> to generate the Cloudinary image URL, and then the image is returned.<\/p>\n\n\n\n<p>This component decouples the image source from the optimization process. The app doesn&#8217;t need to know where the image is hosted. Cloudinary\u2019s fetch function leverages this existing source without re-hosting the image, applying optimizations, and delivering it. This means the original image remains unaltered. This separation of concerns allows for independent updates.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Display the Optimized Image<\/h3>\n\n\n\n<p>First, you will need to set up some test data. The test data will be an array of objects holding four images and the transformation for each image.<\/p>\n\n\n<div class='c-callout  c-callout--inline-title c-callout--note'><strong class='c-callout__title'>Note:<\/strong> <p>In a production application, this data can come from an image storage service or a content management system.<\/p>\n<\/div>\n\n\n<p>To do this, in the src folder, add a new folder called lib; in the lib folder, add a new file called <code>data.ts<\/code>. In the <code>data.ts<\/code> file, add the code that defines the images and their various transformations:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> products: ProductInfo&#91;] = &#91;\n  {\n    <span class=\"hljs-attr\">name<\/span>: <span class=\"hljs-string\">'Dog Lease'<\/span>,\n    <span class=\"hljs-attr\">price<\/span>: <span class=\"hljs-number\">100<\/span>,\n    <span class=\"hljs-attr\">imageUrl<\/span>:\n      <span class=\"hljs-string\">'https:\/\/cloudinary-app.s3.amazonaws.com\/pexels-blue-bird-7210748.jpg'<\/span>,\n    <span class=\"hljs-attr\">transformation<\/span>:\n      <span class=\"hljs-string\">'w_400,h_400,c_scale,q_100,e_auto_brightness,e_auto_color:80'<\/span>,\n  },\n  {\n    <span class=\"hljs-attr\">name<\/span>: <span class=\"hljs-string\">'Dog Food'<\/span>,\n    <span class=\"hljs-attr\">price<\/span>: <span class=\"hljs-number\">100<\/span>,\n    <span class=\"hljs-attr\">imageUrl<\/span>:\n      <span class=\"hljs-string\">'https:\/\/cloudinary-app.s3.amazonaws.com\/pexels-mart-production-8434641.jpg'<\/span>,\n    <span class=\"hljs-attr\">transformation<\/span>:\n      <span class=\"hljs-string\">'w_400,h_400,c_scale,q_100,e_auto_brightness,e_auto_color:80'<\/span>,\n  },\n  {\n    <span class=\"hljs-attr\">name<\/span>: <span class=\"hljs-string\">'Backpack Carrier'<\/span>,\n    <span class=\"hljs-attr\">price<\/span>: <span class=\"hljs-number\">200<\/span>,\n    <span class=\"hljs-attr\">imageUrl<\/span>:\n      <span class=\"hljs-string\">'https:\/\/images.pexels.com\/photos\/8358908\/pexels-photo-8358908.jpeg?auto=compress&amp;cs=tinysrgb&amp;w=1260&amp;h=750&amp;dpr=2'<\/span>,\n    <span class=\"hljs-attr\">transformation<\/span>:\n      <span class=\"hljs-string\">'w_400,h_400,c_scale,q_100,e_auto_brightness,e_auto_color:80'<\/span>,\n  },\n  {\n    <span class=\"hljs-attr\">name<\/span>: <span class=\"hljs-string\">'Dog Toy'<\/span>,\n    <span class=\"hljs-attr\">price<\/span>: <span class=\"hljs-number\">300<\/span>,\n    <span class=\"hljs-attr\">imageUrl<\/span>:\n      <span class=\"hljs-string\">'https:\/\/images.pexels.com\/photos\/20843208\/pexels-photo-20843208\/free-photo-of-dog-with-toy-on-a-brick-pavement.jpeg?auto=compress&amp;cs=tinysrgb&amp;w=1260&amp;h=750&amp;dpr=2'<\/span>,\n    <span class=\"hljs-attr\">transformation<\/span>:\n      <span class=\"hljs-string\">'w_400,h_400,c_scale,q_100,e_auto_brightness,e_auto_color:80'<\/span>,\n  },\n];\n\n<span class=\"hljs-keyword\">export<\/span> interface ProductInfo {\n  <span class=\"hljs-attr\">name<\/span>: string;\n  price: number;\n  imageUrl: string;\n  transformation: string;\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\n\n<p>In the code above, an array named products contains four objects. Each object represents a single product and includes <code>name<\/code>, <code>price<\/code>, <code>imageUrl<\/code>, and <code>transformation<\/code> properties. The first two products have images hosted on Amazon AWS, while the last two use stock images hosted on images.pexels.com. All products conform to the <code>ProductInfo<\/code> interface, which defines the structure of each product object.<\/p>\n\n\n\n<p>All the images use similar transformations. Here\u2019s a detailed explanation of the transformation:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>w_400<\/code>.<\/strong> Sets the width of the image to 400 pixels.<\/li>\n\n\n\n<li><strong><code>h_400<\/code>.<\/strong> Sets the height of the image to 400 pixels.<\/li>\n\n\n\n<li><strong><code>c_scale<\/code>. <\/strong>Resizes the image to the specified width and height without cropping, but the aspect ratio may change.<\/li>\n\n\n\n<li><strong><code>q_100<\/code><\/strong>. Sets the image quality to 100%, which means no compression is applied. The image retains maximum quality.<\/li>\n\n\n\n<li><strong><code>e_auto_brightness<\/code><\/strong>. Automatically adjusts the image&#8217;s brightness to an optimal level.<\/li>\n\n\n\n<li><strong><code>e_auto_color:80<\/code><\/strong>. Automatically adjusts the image&#8217;s color, improving it to 80% of the optimal level. The value 80 fine-tunes the intensity of the color adjustment.<\/li>\n<\/ul>\n\n\n\n<p>By specifying dimensions and scaling options such as <code>w_400<\/code>, <code>h_400<\/code>, and <code>c_scale<\/code>, Cloudinary ensures that the images are resized to the specified dimensions, which helps to prevent our images from being oversized or undersized images, improving both visual appeal and page loading times.\u00a0<\/p>\n\n\n\n<p>Additionally, setting the image quality (q_100) guarantees that the fetched images retain maximum detail while efficiently managing file sizes, enhancing performance across different devices and network conditions. Also, the automatic enhancements e_auto_brightness and e_auto_color:80 provide automated adjustments for brightness and color balance.<\/p>\n\n\n\n<p>Now, in the <code>page.tsx<\/code> file, you&#8217;ll loop over the array to display each transformed image like so:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-keyword\">import<\/span> ImageComponent <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@\/components\/image-card'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/page.module.css'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { ProductInfo, products } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@\/lib\/data'<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> Home: React.FC = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.main}<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>My Pet Store!<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/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\">{styles&#91;<\/span>'<span class=\"hljs-attr\">product-area<\/span>']}&gt;<\/span>\n        {products.map((product: ProductInfo) =&gt; (\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.card}<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{product.name}<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>{product.name}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ImageComponent<\/span>\n              <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{product.imageUrl}<\/span>\n              <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">{product.name}<\/span>\n              <span class=\"hljs-attr\">transformations<\/span>=<span class=\"hljs-string\">{product.transformation}<\/span>\n            \/&gt;<\/span>\n            Price: <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>${product.price}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        ))}\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Home;<\/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\n\n<h2 class=\"wp-block-heading\">The Final Result&nbsp;<\/h2>\n\n\n\n<p>Now run the app and you should see that the <a href=\"https:\/\/paper.dropbox.com\/ep\/redirect\/external-link?url=https%3A%2F%2Fwww.loom.com%2Fshare%2Fd9b32a55d2ce446da2d4557cff44e28d%3Fsid%3Ded7918b6-b82b-4877-a36f-4e1e49c26680&amp;hmac=8TnZNhjKYNcrOCQ4bfvKoMAHcChK0omf8m4K%2BjZeKnE%3D\">transformations you specified<\/a> earlier have been applied to each image in comparison to the original images.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this blog post, we transformed and optimized images hosted on external sources in a Next.js application using Cloudinary\u2019s fetch feature. Expand your app by adding more image transformations and optimizing images fetched from other platforms. <a target=\"_blank\" href=\"https:\/\/cloudinary.com\/\" rel=\"noreferrer noopener\">Learn more<\/a> about how Cloudinary can help get you started today.<\/p>\n\n\n\n<p>If you found this blog post helpful and want to discuss it in more detail, join the <a target=\"_blank\" href=\"https:\/\/community.cloudinary.com\/\" rel=\"noreferrer noopener\">Cloudinary<\/a> <a target=\"_blank\" href=\"https:\/\/community.cloudinary.com\/\" rel=\"noreferrer noopener\">Community forum<\/a> and its associated <a target=\"_blank\" href=\"https:\/\/discord.com\/invite\/cloudinary\" rel=\"noreferrer noopener\">Discord<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Resources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/cloudinary.com\/documentation\/fetch_remote_images#overview\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary Fetch Documentation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/cloudinary.com\/documentation\/transformation_reference#overview\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary Transformation URL API reference<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/nextjs.org\/docs\" target=\"_blank\" rel=\"noreferrer noopener\">Next.js Documentation<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In a composable website, functionality is broken down into independent components, allowing for better flexibility and scalability. This modular approach changes how websites are designed, developed, and maintained. By embracing composability, you build robust and adaptable systems that meet modern standards. In this post, you\u2019ll see how Cloudinary comfortably fits into the composable architecture by [&hellip;]<\/p>\n","protected":false},"author":87,"featured_media":35307,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[98,212,388],"class_list":["post-35303","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-e-commerce","tag-next-js","tag-optimize"],"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>Optimize Your Visuals on a Composable Next.js E-commerce Website<\/title>\n<meta name=\"description\" content=\"Learn to optimize media on a Next.js e-commerce site using Cloudinary. Improve performance with composable architecture and dynamic image fetching.\" \/>\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\/optimize-visuals-composable-next-js-e-commerce-website\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Optimize Your Visuals on a Composable Next.js E-commerce Website\" \/>\n<meta property=\"og:description\" content=\"Learn to optimize media on a Next.js e-commerce site using Cloudinary. Improve performance with composable architecture and dynamic image fetching.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2024-08-19T14:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-08-19T16:38:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog-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\/optimize-visuals-composable-next-js-e-commerce-website#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"Optimize Your Visuals on a Composable Next.js E-commerce Website\",\"datePublished\":\"2024-08-19T14:00:00+00:00\",\"dateModified\":\"2024-08-19T16:38:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website\"},\"wordCount\":1006,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog.jpg?_i=AA\",\"keywords\":[\"E-commerce\",\"Next.js\",\"Optimize\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2024\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website\",\"url\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website\",\"name\":\"Optimize Your Visuals on a Composable Next.js E-commerce Website\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog.jpg?_i=AA\",\"datePublished\":\"2024-08-19T14:00:00+00:00\",\"dateModified\":\"2024-08-19T16:38:52+00:00\",\"description\":\"Learn to optimize media on a Next.js e-commerce site using Cloudinary. Improve performance with composable architecture and dynamic image fetching.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog.jpg?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Optimize Your Visuals on a Composable Next.js E-commerce Website\"}]},{\"@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":"Optimize Your Visuals on a Composable Next.js E-commerce Website","description":"Learn to optimize media on a Next.js e-commerce site using Cloudinary. Improve performance with composable architecture and dynamic image fetching.","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\/optimize-visuals-composable-next-js-e-commerce-website","og_locale":"en_US","og_type":"article","og_title":"Optimize Your Visuals on a Composable Next.js E-commerce Website","og_description":"Learn to optimize media on a Next.js e-commerce site using Cloudinary. Improve performance with composable architecture and dynamic image fetching.","og_url":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website","og_site_name":"Cloudinary Blog","article_published_time":"2024-08-19T14:00:00+00:00","article_modified_time":"2024-08-19T16:38:52+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog-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\/optimize-visuals-composable-next-js-e-commerce-website#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"Optimize Your Visuals on a Composable Next.js E-commerce Website","datePublished":"2024-08-19T14:00:00+00:00","dateModified":"2024-08-19T16:38:52+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website"},"wordCount":1006,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog.jpg?_i=AA","keywords":["E-commerce","Next.js","Optimize"],"inLanguage":"en-US","copyrightYear":"2024","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website","url":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website","name":"Optimize Your Visuals on a Composable Next.js E-commerce Website","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog.jpg?_i=AA","datePublished":"2024-08-19T14:00:00+00:00","dateModified":"2024-08-19T16:38:52+00:00","description":"Learn to optimize media on a Next.js e-commerce site using Cloudinary. Improve performance with composable architecture and dynamic image fetching.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog.jpg?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/optimize-visuals-composable-next-js-e-commerce-website#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Optimize Your Visuals on a Composable Next.js E-commerce Website"}]},{"@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\/v1723224685\/optimized_visuals_Nextjs_ecomm_site-blog\/optimized_visuals_Nextjs_ecomm_site-blog.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/35303","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=35303"}],"version-history":[{"count":1,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/35303\/revisions"}],"predecessor-version":[{"id":35306,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/35303\/revisions\/35306"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/35307"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=35303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=35303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=35303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}