{"id":39783,"date":"2026-02-11T07:00:00","date_gmt":"2026-02-11T15:00:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=39783"},"modified":"2026-02-12T11:06:06","modified_gmt":"2026-02-12T19:06:06","slug":"layout-shifts-conditional-transformations","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations","title":{"rendered":"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Modern web development often feels like a trade-off between complex UI needs and performance. When we handle user-generated content, we rely on brittle client-side logic <code>useEffect<\/code> hooks and conditional CSS to manage different image orientations. This approach bloats the JavaScript bundle and triggers Cumulative Layout Shift (CLS) as the browser waits for image metadata to load.<\/p>\n<p>With <strong>Smart Component Philosophy<\/strong>, we instead calculate layout logic in the user\u2019s browser, and offload it to Cloudinary. By using conditional parameters like <code>if_ar_lt_1.0<\/code> (detecting portrait orientation), we create components that automatically identify image orientation on the CDN, apply backgrounds or padding before the pixels even reach the browser, and eliminate layout shifts and reduce client-side execution to improve Core Web Vitals.<\/p>\n<p>This guide shows you how to build these autonomous components using Next.js 16, ensuring your media pipeline is fast, intelligent, and scalable.<\/p>\n<p><strong>Live Demo:<\/strong> <a href=\"https:\/\/optiflow-eta.vercel.app\/\">https:\/\/optiflow-eta.vercel.app<\/a><\/p>\n<p><strong>Github:<\/strong> <a href=\"https:\/\/github.com\/musebe\/optiflow\">https:\/\/github.com\/musebe\/optiflow<\/a><\/p>\n<h2>The Problem: The Hidden Cost of \u2018Naive\u2019 Media<\/h2>\n<p>Modern Next.js applications use manual conditional logic to manage diverse user-generated assets. When a social feed or gallery needs to handle both portrait and landscape images, developers tend to reach for brittle <code>if-else<\/code> statements within the React component.<\/p>\n<p>This \u201cnaive\u201d approach creates two major engineering bottlenecks:<\/p>\n<ul>\n<li>\n<strong>Bundle bloat.<\/strong> Handling orientation requires fetching image metadata and executing custom hooks like <code>useEffect<\/code> to determine dimensions. This adds unnecessary JavaScript to the client bundle.<\/li>\n<li>\n<strong>CLS.<\/strong> Because the browser must wait for the image to load before the logic can calculate the correct styles, the page often jumps or re-renders. This delay degrades the user experience and lowers Core Web Vitals scores.<\/li>\n<\/ul>\n<p>The core issue is that the application code is doing the heavy lifting for tasks that are better suited for the delivery layer. This results in a \u201cnaive\u201d baseline where images are often letterboxed with static gray bars, creating a disjointed and unpolished design.<\/p>\n<h2>Project Initialization and Environment<\/h2>\n<p>To build a high-performance media pipeline, we start with a Next.js 16 foundation using <strong>Turbopack<\/strong> for rapid development. The critical step is enabling the unified caching model, which consolidates several experimental flags into a single, manageable configuration.<\/p>\n<p>First, initialize the project:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">npx<\/span> <span class=\"hljs-selector-tag\">create-next-app<\/span><span class=\"hljs-keyword\">@latest<\/span> optiflow --typescript --tailwind --eslint\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The engine of our setup lives in the configuration. In Next.js 16, we use the <code>cacheComponents<\/code> flag to enable the <code>use cache<\/code> directive and Partial Prerendering (PPR) globally.<\/p>\n<h3>The Configuration Engine<\/h3>\n<p>Update your <code>next.config.ts<\/code> to flip the master switch for advanced caching:<\/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-comment\">\/\/ next.config.ts<\/span>\n<span class=\"hljs-keyword\">import<\/span> type { NextConfig } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\"<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> nextConfig: NextConfig = {\n  <span class=\"hljs-comment\">\/\/ Enables use cache, ppr, and dynamicIO in Next.js 16+<\/span>\n  <span class=\"hljs-attr\">cacheComponents<\/span>: <span class=\"hljs-literal\">true<\/span>,\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> nextConfig;\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<blockquote>\n<p>View the file on GitHub: <a href=\"https:\/\/github.com\/musebe\/optiflow\/blob\/main\/next.config.ts\">next.config.ts<\/a><\/p>\n<\/blockquote>\n<p>By setting <code>cacheComponents<\/code> to true, we ensure that data fetching operations are excluded from pre-renders unless explicitly cached, allowing for fresh runtime data by default.<\/p>\n<h2>Cloudinary Technical Setup<\/h2>\n<p>Connecting Next.js 16 to the Cloudinary ecosystem requires a secure handshake between your environment variables and the SDK. This setup ensures that your API secrets remain on the server while the public cloud name is accessible for client-side rendering.<\/p>\n<h3>The Environment Engine<\/h3>\n<p>First, populate your <code>.env.local<\/code> with the credentials found in your Cloudinary Dashboard. We use the <code>NEXT_PUBLIC_<\/code> prefix only for the Cloud Name and Upload Preset to keep the API Secret protected.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\"><span class=\"hljs-comment\"># .env.local<\/span>\nNEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=<span class=\"hljs-string\">\"your_cloud_name\"<\/span>\nNEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET=<span class=\"hljs-string\">\"optiflow-preset\"<\/span>\n\nCLOUDINARY_API_KEY=<span class=\"hljs-string\">\"your_api_key\"<\/span>\nCLOUDINARY_API_SECRET=<span class=\"hljs-string\">\"your_api_secret\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h3>SDK Initialization<\/h3>\n<p>In the library layer, we configure the singleton instance of the Cloudinary SDK. This engine handles the signature generation for authenticated requests, such as searching for assets in specific folders.<\/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-comment\">\/\/ lib\/media.ts<\/span>\n<span class=\"hljs-keyword\">import<\/span> { v2 <span class=\"hljs-keyword\">as<\/span> cloudinary } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'cloudinary'<\/span>;\n\ncloudinary.config({\n  <span class=\"hljs-attr\">cloud_name<\/span>: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME,\n  <span class=\"hljs-attr\">api_key<\/span>: process.env.CLOUDINARY_API_KEY,\n  <span class=\"hljs-attr\">api_secret<\/span>: process.env.CLOUDINARY_API_SECRET,\n  <span class=\"hljs-attr\">secure<\/span>: <span class=\"hljs-literal\">true<\/span>,\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<blockquote>\n<p>View the file on <a href=\"https:\/\/github.com\/musebe\/optiflow\/blob\/main\/lib\/media.ts\">GitHub: lib\/media.ts<\/a><\/p>\n<\/blockquote>\n<p>Finally, ensure your <strong>Upload Preset<\/strong> in the Cloudinary Settings is set to \u201cUnsigned\u201d and pointed at the <code>optiflow-media<\/code> folder to allow the <code>CldUploadWidget<\/code> to communicate without custom backend signatures.<\/p>\n<h2>The Data Layer, Server-Side Media Fetching<\/h2>\n<p>Before we can fetch our assets, we need to install the necessary packages to bridge the gap between Next.js and Cloudinary.<\/p>\n<h3>Installation<\/h3>\n<p>Run the following command to add the server-side SDK and the Next.js-specific components:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npm install cloudinary next-cloudinary\n<\/code><\/span><\/pre>\n<h3>The Fetching Engine<\/h3>\n<p>With the tools in place, we implement the data fetching logic using the Cloudinary Search API. This engine is wrapped in the Next.js 16 <code>use cache<\/code> directive, which ensures high performance while allowing for instant revalidation when new media is uploaded.<\/p>\n<p>By using the Search API, we bypass traditional folder restrictions and can sort our \u201cSmart Assets\u201d by creation date natively on the CDN.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">\/\/ lib\/media.ts snippet\n\nexport async function getOptiFlowMedia(): Promise<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CloudinaryResource&#91;]<\/span>&gt;<\/span> {\n  \"use cache\";\n\n  try {\n    const result = await cloudinary.search\n      .expression('folder:optiflow-media')\n      .sort_by('created_at', 'desc')\n      .max_results(12)\n      .execute();\n\n    return result.resources as CloudinaryResource&#91;];\n  } catch (error: unknown) {\n    console.error(\"\u274c OptiFlow Search API Error:\", error);\n    return &#91;];\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><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<blockquote>\n<p>View the file on GitHub: <a href=\"https:\/\/github.com\/musebe\/optiflow\/blob\/main\/lib\/media.ts\">https:\/\/github.com\/musebe\/optiflow\/blob\/main\/lib\/media.ts<\/a><\/p>\n<\/blockquote>\n<p>This server-side approach keeps our API secrets hidden and ensures that the client only receives the final, optimized list of assets.<\/p>\n<h2>Building the \u2018Naive\u2019 Baseline<\/h2>\n<p>To appreciate the \u201cSmart\u201d solution, we\u2019ll first build the <strong>Naive<\/strong> baseline. This component represents the traditional way of handling images: forcing every asset into a fixed container with static padding.<\/p>\n<h3>The Naive Engine<\/h3>\n<p>This component uses standard letterboxing. If a user uploads a portrait image into our 16:9 gallery, the browser simply adds gray bars to the sides to prevent stretching. There\u2019s no intelligence here. The component treats a vertical reindeer the same as a horizontal landscape.<\/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-comment\">\/\/ components\/media\/naive-image.tsx snippet<\/span>\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">NaiveImage<\/span>(<span class=\"hljs-params\">{ asset, priority = false }: NaiveImageProps<\/span>) <\/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\">\"relative aspect-video w-full overflow-hidden rounded-lg bg-neutral-200\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CldImage<\/span>\n        <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"800\"<\/span>\n        <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"450\"<\/span>\n        <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{asset.public_id}<\/span>\n        <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"Naive Asset\"<\/span>\n        <span class=\"hljs-attr\">crop<\/span>=<span class=\"hljs-string\">\"pad\"<\/span>\n        <span class=\"hljs-attr\">background<\/span>=<span class=\"hljs-string\">\"rgb:d4d4d4\"<\/span>\n        <span class=\"hljs-attr\">priority<\/span>=<span class=\"hljs-string\">{priority}<\/span>\n        <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"object-contain\"<\/span>\n      \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\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<blockquote>\n<p>View the file on GitHub: <a href=\"https:\/\/github.com\/musebe\/optiflow\/blob\/main\/components\/media\/naive-image.tsx\">https:\/\/github.com\/musebe\/optiflow\/blob\/main\/components\/media\/naive-image.tsx<\/a><\/p>\n<\/blockquote>\n<p>While this prevents distortion, it creates a \u201cdead zone\u201d in your UI. In a professional production environment, this static approach often leads to the bundle-bloating <code>useEffect<\/code> hooks we discussed earlier as developers try to \u201cfix\u201d the gray bars manually on the client.<\/p>\n<h2>Engineering the Smart Component<\/h2>\n<p>This is where we\u2019ll move from static padding to automated intelligence. The <strong>Smart Component<\/strong> replaces the brittle \u201cnaive\u201d logic with a declarative instruction sent directly to the Cloudinary CDN.<\/p>\n<h3>The Smart Engine<\/h3>\n<p>The engine utilizes the <code>fillBackground<\/code> prop, which acts as a wrapper for Cloudinary\u2019s conditional transformation logic. When an image is detected as portrait (), the CDN automatically generates a blurred version of the original asset to fill the remaining 16:9 space.<\/p>\n<p>This happens on the delivery layer. The browser receives a single, perfectly formatted image, eliminating the need for client-side orientation checks or layout recalculations.<\/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-comment\">\/\/ components\/media\/smart-image.tsx snippet<\/span>\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">SmartImage<\/span>(<span class=\"hljs-params\">{ asset, priority = false }: SmartImageProps<\/span>) <\/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\">\"relative aspect-video w-full overflow-hidden rounded-lg bg-neutral-100 border border-sky-100\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CldImage<\/span>\n        <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"800\"<\/span>\n        <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"450\"<\/span>\n        <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{asset.public_id}<\/span>\n        <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">{asset.context?.custom?.alt<\/span> || \"<span class=\"hljs-attr\">OptiFlow<\/span> <span class=\"hljs-attr\">Smart<\/span> <span class=\"hljs-attr\">Asset<\/span>\"}\n        <span class=\"hljs-attr\">crop<\/span>=<span class=\"hljs-string\">\"fill\"<\/span>\n        <span class=\"hljs-attr\">fillBackground<\/span>=<span class=\"hljs-string\">{{<\/span>\n          <span class=\"hljs-attr\">crop:<\/span> \"<span class=\"hljs-attr\">pad<\/span>\",\n          <span class=\"hljs-attr\">gravity:<\/span> \"<span class=\"hljs-attr\">center<\/span>\",\n        }}\n        <span class=\"hljs-attr\">priority<\/span>=<span class=\"hljs-string\">{priority}<\/span>\n        <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"transition-all duration-500 hover:scale-&#91;1.02]\"<\/span>\n      \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\n}\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<blockquote>\n<p>View the file on GitHub: <a href=\"https:\/\/github.com\/musebe\/optiflow\/blob\/main\/components\/media\/smart-image.tsx\">https:\/\/github.com\/musebe\/optiflow\/blob\/main\/components\/media\/smart-image.tsx<\/a><\/p>\n<\/blockquote>\n<p>By offloading this logic, we\u2019ll eliminate CLS while writing less code to handle more edge cases.<\/p>\n<h2>The \u2018Aha!\u2019 Moment: The Code Comparison<\/h2>\n<p>The true power of the Smart Component philosophy becomes clear when you compare the naive React code against the \u201cSmart\u201d declaration.<\/p>\n<h3>The Brittle \u2018Naive\u2019 Logic<\/h3>\n<p>In a traditional Next.js application, achieving a blurred background for portrait images can require over 30 lines of client-side code. You\u2019d typically need a <code>useEffect<\/code> to fetch image metadata, state to track the orientation, and complex conditional CSS classes to handle the background rendering. This logic runs in the user\u2019s browser, consuming CPU cycles and increasing the risk of layout shifts.<\/p>\n<h3>The Declarative \u2018Smart\u2019 Solution<\/h3>\n<p>With the Smart Component, that entire logic block is replaced by a single prop: <code>fillBackground<\/code>.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ The \"Smart\" Engine in one declaration<\/span>\n\n&lt;CldImage\n  src={asset.public_id}\n  width=<span class=\"hljs-string\">\"800\"<\/span>\n  height=<span class=\"hljs-string\">\"450\"<\/span>\n  crop=<span class=\"hljs-string\">\"fill\"<\/span>\n  fillBackground <span class=\"hljs-comment\">\/\/ This triggers the CDN-side orientation logic<\/span>\n\/&gt;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>By passing this instruction to the Cloudinary CDN, the \u201cif-this-then-that\u201d logic happens before the image is even downloaded. The browser receives a finished asset that fits the 16:9 container perfectly, meaning zero layout recalculations and zero custom CSS for orientation.<\/p>\n<p>This transition represents the \u201cAha!\u201d moment: We aren\u2019t just writing shorter code. We\u2019re building more resilient components that perform better by default.<\/p>\n<h2>Automation and Performance: Revalidation and LCP<\/h2>\n<p>A smart component is only as good as its delivery speed. In this phase, we\u2019ll optimize the \u201cOptiFlow\u201d engine to handle real-time data updates and critical performance metrics like <strong>Largest Contentful Paint (LCP)<\/strong>.<\/p>\n<h3>The Revalidation Engine<\/h3>\n<p>When a user uploads a new image, we want it to appear in the gallery instantly without a hard browser refresh. We\u2019ll achieve this using a Next.js 16 <strong>Server Action<\/strong>. By calling <code>revalidatePath<\/code>, we\u2019ll purge the server-side cache for the gallery route the moment the Cloudinary upload is successful.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ app\/actions\/media.ts<\/span>\n\n<span class=\"hljs-string\">\"use server\"<\/span>;\n\n<span class=\"hljs-keyword\">import<\/span> { revalidatePath } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'next\/cache'<\/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\">revalidateMedia<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-comment\">\/\/ Purges the cache for the home page gallery<\/span>\n  revalidatePath(<span class=\"hljs-string\">'\/'<\/span>);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><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<blockquote>\n<p>View the file on GitHub: <a href=\"https:\/\/github.com\/musebe\/optiflow\/blob\/main\/app\/actions\/media.ts\">https:\/\/github.com\/musebe\/optiflow\/blob\/main\/app\/actions\/media.ts<\/a><\/p>\n<\/blockquote>\n<h3>Solving for Largest Contentful Paint<\/h3>\n<p>The Next.js 16 compiler often flags \u201cabove-the-fold\u201d images as the LCP. To solve this, we\u2019ll implement a priority loading strategy in our <code>SmartGallery<\/code>. By passing the <code>priority<\/code> prop to the first two image pairs, we\u2019ll tell the browser to download these assets immediately, improving our performance score.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ components\/media\/smart-gallery.tsx snippet<\/span>\n\n{assets.map(<span class=\"hljs-function\">(<span class=\"hljs-params\">asset, index<\/span>) =&gt;<\/span> {\n  <span class=\"hljs-comment\">\/\/ Mark the first 2 images as high priority<\/span>\n  <span class=\"hljs-keyword\">const<\/span> isPriority = index &lt; <span class=\"hljs-number\">2<\/span>;\n\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\">key<\/span>=<span class=\"hljs-string\">{asset.public_id}<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">SmartImage<\/span> <span class=\"hljs-attr\">asset<\/span>=<span class=\"hljs-string\">{asset}<\/span> <span class=\"hljs-attr\">priority<\/span>=<span class=\"hljs-string\">{isPriority}<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\n})}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><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<blockquote>\n<p>View the file on GitHub: <a href=\"https:\/\/github.com\/musebe\/optiflow\/blob\/main\/components\/media\/smart-gallery.tsx\">https:\/\/github.com\/musebe\/optiflow\/blob\/main\/components\/media\/smart-gallery.tsx<\/a><\/p>\n<\/blockquote>\n<p>By combining server-side revalidation with prioritized client-side loading, the engine stays both fresh and fast, meeting the strict performance requirements (Rick) of a modern enterprise application.<\/p>\n<h2>Scale Your Design Systems With Cloudinary<\/h2>\n<p>The OptiFlow project demonstrates that smart engineering is building systems that are resilient to the chaos of UGC. By shifting visual logic from the browser to the Cloudinary, we achieved our core objectives:<\/p>\n<ul>\n<li>Eliminated CLS and improved LCP by delivering preformatted assets directly from the CDN.<\/li>\n<li>Removed the need for brittle orientation-check helpers and complex CSS overrides, reducing the media component to a single, declarative tag.<\/li>\n<li>Unified design language across thousands of assets without manual intervention or extra client-side JavaScript.<\/li>\n<\/ul>\n<p>As web standards move toward more autonomous and \u201cedge-heavy\u201d architectures, the <strong>Smart Component Philosophy<\/strong> provides a blueprint for building media-rich applications that stay fast, lean, and maintainable.<\/p>\n<p>Thank you for following along with this engineering deep dive. <a href=\"https:\/\/cloudinary.com\/users\/register_free\">Sign up<\/a> for a free Cloudinary today to get started, or find the full implementation and explore the live environment below:<\/p>\n<p><strong>Live demo:<\/strong> <a href=\"https:\/\/optiflow-eta.vercel.app\/\">https:\/\/optiflow-eta.vercel.app\/<\/a><\/p>\n<p><strong>GitHub repository:<\/strong> <a href=\"https:\/\/github.com\/musebe\/optiflow\">https:\/\/github.com\/musebe\/optiflow<\/a><\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":87,"featured_media":39793,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[72,212,227],"class_list":["post-39783","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-core-web-vitals","tag-next-js","tag-performance-optimization"],"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>Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations<\/title>\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\/layout-shifts-conditional-transformations\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-11T15:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-02-12T19:06:06+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.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\/layout-shifts-conditional-transformations#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations\",\"datePublished\":\"2026-02-11T15:00:00+00:00\",\"dateModified\":\"2026-02-12T19:06:06+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations\"},\"wordCount\":12,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.jpg?_i=AA\",\"keywords\":[\"Core Web Vitals\",\"Next.js\",\"Performance Optimization\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations\",\"url\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations\",\"name\":\"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.jpg?_i=AA\",\"datePublished\":\"2026-02-11T15:00:00+00:00\",\"dateModified\":\"2026-02-12T19:06:06+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.jpg?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations\"}]},{\"@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":"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations","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\/layout-shifts-conditional-transformations","og_locale":"en_US","og_type":"article","og_title":"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations","og_url":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations","og_site_name":"Cloudinary Blog","article_published_time":"2026-02-11T15:00:00+00:00","article_modified_time":"2026-02-12T19:06:06+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.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\/layout-shifts-conditional-transformations#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations","datePublished":"2026-02-11T15:00:00+00:00","dateModified":"2026-02-12T19:06:06+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations"},"wordCount":12,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.jpg?_i=AA","keywords":["Core Web Vitals","Next.js","Performance Optimization"],"inLanguage":"en-US","copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations","url":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations","name":"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.jpg?_i=AA","datePublished":"2026-02-11T15:00:00+00:00","dateModified":"2026-02-12T19:06:06+00:00","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.jpg?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/layout-shifts-conditional-transformations#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Engineering Smart Next.js Components: Solving Layout Shifts With Cloudinary Conditional Transformations"}]},{"@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\/v1770855456\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations\/Blog_Engineering_Smart_Next.js_Components__Solving_Layout_Shifts_with_Cloudinary_Conditional_Transformations.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/39783","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=39783"}],"version-history":[{"count":1,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/39783\/revisions"}],"predecessor-version":[{"id":39784,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/39783\/revisions\/39784"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/39793"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=39783"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=39783"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=39783"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}