{"id":28367,"date":"2022-03-23T22:02:10","date_gmt":"2022-03-23T22:02:10","guid":{"rendered":"http:\/\/Build-an-Image-Gallery-with-Next.js"},"modified":"2025-02-25T16:07:16","modified_gmt":"2025-02-26T00:07:16","slug":"build-an-image-gallery-with-next-js","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/","title":{"rendered":"Build an Image Gallery"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>In this Media Jam, we will build an Image Gallery and use the\u00a0<a href=\"https:\/\/nextjs.org\/blog\/next-10#built-in-image-component-and-automatic-image-optimization\">Next.js Image component<\/a>\u00a0to optimize the images fetched from the Pexels API.<\/p>\n<p>This gallery will show the list of curated photos by the Pexels team, and has a dynamic route to them. The users will also be able to search for images using this gallery.<\/p>\n<h2>Sandbox<\/h2>\n<p>You can play and explore the code described in this Jam on <a href=\"https:\/\/codesandbox.io\/s\/next-image-gallery-4lkte?file=\/pages\/index.js\">CodeSandbox<\/a>. The code to display and search through the photos can be found in <code>src\/pages\/index.js<\/code>. The <code>src\/pages\/photos\/[id].js<\/code> file contains the code to create dynamic routes for the pics.<\/p>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/next-image-gallery-4lkte?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=%2Fpages%2Findex.js&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"Next Image Gallery\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><h2>How to fetch and display the images?<\/h2>\n<p>To fetch the images, we will create a file named <code>api.js<\/code> in the <code>lib<\/code> directory. Inside this file, we will create a function to fetch the data using the <code>fetch<\/code> method.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">const<\/span> API_KEY = process.env.NEXT_PUBLIC_PEXELS_API_KEY;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> getCuratedPhotos = <span class=\"hljs-keyword\">async<\/span> () =&gt; {\n  <span class=\"hljs-keyword\">const<\/span> res = <span class=\"hljs-keyword\">await<\/span> fetch(\n    <span class=\"hljs-string\">`https:\/\/api.pexels.com\/v1\/curated?page=11&amp;per_page=18`<\/span>,\n    {\n      <span class=\"hljs-attr\">headers<\/span>: {\n        <span class=\"hljs-attr\">Authorization<\/span>: API_KEY,\n      },\n    }\n  );\n  <span class=\"hljs-keyword\">const<\/span> responseJson = <span class=\"hljs-keyword\">await<\/span> res.json();\n  <span class=\"hljs-keyword\">return<\/span> responseJson.photos;\n};\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>If you take a closer look at the fetch URL, you will notice that we have added <code>?page=11&amp;per_page=18<\/code> after the <code>\/curated<\/code> endpoint. These are the optional parameters that you can pass to the <code>\/curated<\/code> endpoint as query strings. Here <code>page=11<\/code> means send the 11th page, and <code>per_page=18<\/code> means that send 18 photos per page.<\/p>\n<p>We will use the <code>getServerSideProps()<\/code> function available in Next.js and use the <code>getCuratedPhotos()<\/code> function inside it to fetch data from Pexels API and inject it in our page. You can read more about <code>getServerSideProps()<\/code> <a href=\"https:\/\/nextjs.org\/docs\/basic-features\/data-fetching#getserversideprops-server-side-rendering\">here<\/a>.<\/p>\n<p>Add the following code at the bottom of your <code>index.js<\/code> file:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getServerSideProps<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> data = <span class=\"hljs-keyword\">await<\/span> getCuratedPhotos();\n  <span class=\"hljs-keyword\">return<\/span> {\n    <span class=\"hljs-attr\">props<\/span>: {\n      data,\n    },\n  };\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The above async function uses <code>getCuratedPhotos()<\/code> to fetch images from the Pexels API and store them in the <code>data<\/code> variable. This <code>data<\/code> variable is made available as a prop in the <code>props<\/code> property.<\/p>\n<p>This <code>data<\/code> is available as a prop, so add it as an argument in the <code>Home<\/code> component function.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Home<\/span>(<span class=\"hljs-params\">{data}<\/span>) <\/span>{\n<span class=\"hljs-keyword\">const<\/span> &#91;photos, setPhotos] = useState(data);\n...\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You could store the images in a <a href=\"https:\/\/reactjs.org\/docs\/state-and-lifecycle.html\">React State<\/a> named <code>photos<\/code>, and then map over it to display the pictures using the <code>img<\/code> element.<\/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\">{\n  photos.map(<span class=\"hljs-function\">(<span class=\"hljs-params\">pic<\/span>) =&gt;<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{pic.src.original}<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span> <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"500\"<\/span> \/&gt;<\/span><\/span>\n  ))\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<h2>Why should you optimize the images in your app?<\/h2>\n<p>A high definition image can range anywhere from 10MB to 100MB in size or more based on the image\u2019s quality.<\/p>\n<p>Imagine you have 80 images on your app\u2019s landing page. Does it make sense to transfer around 800 MB of files every time someone visits your Gallery or website? <strong>It does not<\/strong>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1615030328\/e-603fc45fe6c0b4006873802f\/zllksif5m69w3kagimsa.png\" alt=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/v1615030328\/e-603fc45fe6c0b4006873802f\/zllksif5m69w3kagimsa.png\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1810\" height=\"700\"\/><\/p>\n<p>This is why today, most of the images on the web are served in <a href=\"https:\/\/en.wikipedia.org\/wiki\/WebP\">WebP<\/a> format. This format significantly <strong>reduces the size<\/strong> of the image, and you can <strong>hardly detect any visual difference<\/strong>.<\/p>\n<p>So, we need to change the image format to <code>webp<\/code>, but the question is, how? Do you need to do it manually? If yes, won\u2019t it be time consuming and tiresome?<\/p>\n<p><strong>No, you don\u2019t need to do it manually.<\/strong><\/p>\n<p><a href=\"https:\/\/nextjs.org\/blog\/next-10\">Next.js version 10<\/a> comes with built-in support for Image Optimization using the <strong>Image<\/strong> component. You can read more about this update <a href=\"https:\/\/nextjs.org\/blog\/next-10#built-in-image-component-and-automatic-image-optimization\">here<\/a>.<\/p>\n<h2>How to optimize images using the Next.js Image component?<\/h2>\n<p>First, you need to import this component in <code>index.js<\/code>.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> Image <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/image\"<\/span>;\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<p>You will need to use this component to display the images instead of <code>img<\/code> element.<\/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\">{\n  photos.map(<span class=\"hljs-function\">(<span class=\"hljs-params\">pic<\/span>) =&gt;<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Image<\/span>\n      <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{pic.src.portrait}<\/span>\n      <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">{600}<\/span>\n      <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">{400}<\/span>\n      <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">{pic.url}<\/span>\n    \/&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<p>You will also need to create a <code>next.config.js<\/code> file to tell Next.js to trust the domain where the images are coming from. Add the following code to <code>next.config.js<\/code>:<\/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-built_in\">module<\/span>.exports = {\n  <span class=\"hljs-attr\">images<\/span>: {\n    <span class=\"hljs-attr\">domains<\/span>: &#91;<span class=\"hljs-string\">\"images.pexels.com\"<\/span>],\n  },\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<p>This component will optimize the images fetched from Pexels.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1615030692\/e-603fc45fe6c0b4006873802f\/fiwjqdq8ofrddwhqjww3.png\" alt=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/v1615030692\/e-603fc45fe6c0b4006873802f\/fiwjqdq8ofrddwhqjww3.png\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1455\" height=\"486\"\/><\/p>\n<p>The Next.js Image component has also added <a href=\"https:\/\/en.wikipedia.org\/wiki\/Lazy_loading\">lazy loading<\/a> to images. Here is an example to explain how and why you should use lazy loading if you are unfamiliar with it.<\/p>\n<p>Even though the images are now in <code>webp<\/code> format, is it necessary to load all the images whenever someone visits your website? And if the visitor just comes and leaves without scrolling, does it make sense to load the images at the bottom of the page?<\/p>\n<p>There is no need to load the images that a user or visitor is not going to see in most situations.<\/p>\n<p>And that\u2019s where <strong>Lazy Loading<\/strong> comes to save the day. It delays the requests to images as to when they are needed, or in this situation, when images come into view. This helps to significantly reduce the initial page weight, and improves website performance.<\/p>\n<p>If you head over to <a href=\"http:\/\/localhost:3000\/\">http:\/\/localhost:3000\/<\/a> and scroll through all the images, you will see that the images that are not in the viewport are not loaded initially. But as you scroll down, they are transferred and loaded.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1615030531\/e-603fc45fe6c0b4006873802f\/nex7lj6ydmvkjjhwetde.gif\" alt=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/v1615030531\/e-603fc45fe6c0b4006873802f\/nex7lj6ydmvkjjhwetde.gif\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"600\" height=\"278\"\/><\/p>\n<h2>What\u2019s next?<\/h2>\n<p>You could further develop this project and add other features and functionalities to it. Maybe you could start by adding animations, using <a href=\"https:\/\/www.framer.com\/motion\/\">Framer Motion<\/a>!<\/p>\n<p>Here are some additional resources that can be helpful:<\/p>\n<ul>\n<li>\n<a href=\"https:\/\/www.freecodecamp.org\/news\/build-an-image-gallery-with-nextjs\/\">How to Build an Image Gallery with NextJS using the Pexels API and Chakra UI<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/nextjs.org\/docs\/getting-started\">Next.js Docs<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/cloudinary.com\/documentation\/image_optimization#what_is_image_optimization\">What is image optimization?<\/a>\n<\/li>\n<\/ul>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28368,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,370,212,371,321],"class_list":["post-28367","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-image","tag-next-js","tag-under-review","tag-webp"],"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>Build an Image Gallery<\/title>\n<meta name=\"description\" content=\"In this Media Jam, we will build an Image Gallery and use the Next.js Image component to optimize the images fetched from the Pexels API. This gallery will show the list of curated photos by the Pexels team and has a dynamic route to them. The users will also be able to search for images using this gallery.\" \/>\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\/guest_post\/build-an-image-gallery-with-next-js\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build an Image Gallery\" \/>\n<meta property=\"og:description\" content=\"In this Media Jam, we will build an Image Gallery and use the Next.js Image component to optimize the images fetched from the Pexels API. This gallery will show the list of curated photos by the Pexels team and has a dynamic route to them. The users will also be able to search for images using this gallery.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-03-23T22:02:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-02-26T00:07:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f-jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"6000\" \/>\n\t<meta property=\"og:image:height\" content=\"3376\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\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\/guest_post\/build-an-image-gallery-with-next-js\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Build an Image Gallery\",\"datePublished\":\"2022-03-23T22:02:10+00:00\",\"dateModified\":\"2025-02-26T00:07:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/\"},\"wordCount\":4,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"Image\",\"Next.js\",\"Under Review\",\"WebP\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/\",\"name\":\"Build an Image Gallery\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f.jpg?_i=AA\",\"datePublished\":\"2022-03-23T22:02:10+00:00\",\"dateModified\":\"2025-02-26T00:07:16+00:00\",\"description\":\"In this Media Jam, we will build an Image Gallery and use the Next.js Image component to optimize the images fetched from the Pexels API. This gallery will show the list of curated photos by the Pexels team and has a dynamic route to them. The users will also be able to search for images using this gallery.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f.jpg?_i=AA\",\"width\":6000,\"height\":3376},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Build an Image Gallery\"}]},{\"@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\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Build an Image Gallery","description":"In this Media Jam, we will build an Image Gallery and use the Next.js Image component to optimize the images fetched from the Pexels API. This gallery will show the list of curated photos by the Pexels team and has a dynamic route to them. The users will also be able to search for images using this gallery.","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\/guest_post\/build-an-image-gallery-with-next-js\/","og_locale":"en_US","og_type":"article","og_title":"Build an Image Gallery","og_description":"In this Media Jam, we will build an Image Gallery and use the Next.js Image component to optimize the images fetched from the Pexels API. This gallery will show the list of curated photos by the Pexels team and has a dynamic route to them. The users will also be able to search for images using this gallery.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-03-23T22:02:10+00:00","article_modified_time":"2025-02-26T00:07:16+00:00","og_image":[{"width":6000,"height":3376,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f-jpg?_i=AA","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/"},"author":{"name":"","@id":""},"headline":"Build an Image Gallery","datePublished":"2022-03-23T22:02:10+00:00","dateModified":"2025-02-26T00:07:16+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/"},"wordCount":4,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f.jpg?_i=AA","keywords":["Guest Post","Image","Next.js","Under Review","WebP"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/","name":"Build an Image Gallery","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f.jpg?_i=AA","datePublished":"2022-03-23T22:02:10+00:00","dateModified":"2025-02-26T00:07:16+00:00","description":"In this Media Jam, we will build an Image Gallery and use the Next.js Image component to optimize the images fetched from the Pexels API. This gallery will show the list of curated photos by the Pexels team and has a dynamic route to them. The users will also be able to search for images using this gallery.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f.jpg?_i=AA","width":6000,"height":3376},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-image-gallery-with-next-js\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Build an Image Gallery"}]},{"@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":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924678\/Web_Assets\/blog\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f\/5d3157c6d5048e5d848cab92fc05b34cb1a593a9-6000x3376-1_283685732f.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28367","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\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28367"}],"version-history":[{"count":1,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28367\/revisions"}],"predecessor-version":[{"id":37026,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28367\/revisions\/37026"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28368"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28367"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28367"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}