<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tom Dale</title>
    <description>The latest articles on DEV Community by Tom Dale (@daletom).</description>
    <link>https://dev.to/daletom</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F74094%2F545b1dde-c7c9-447f-ba4f-0633361555a9.png</url>
      <title>DEV Community: Tom Dale</title>
      <link>https://dev.to/daletom</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/daletom"/>
    <language>en</language>
    <item>
      <title>My Journey Helping with the imgix component for Nuxt Image</title>
      <dc:creator>Tom Dale</dc:creator>
      <pubDate>Fri, 24 Sep 2021 14:19:13 +0000</pubDate>
      <link>https://dev.to/daletom/using-the-new-nuxt-image-component-with-imgix-133l</link>
      <guid>https://dev.to/daletom/using-the-new-nuxt-image-component-with-imgix-133l</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BGCtMhUc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.imgix.net/blog/nuxt/imgix_plus_nuxt.ai%3Fw%3D1678%26dpr%3D2" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BGCtMhUc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.imgix.net/blog/nuxt/imgix_plus_nuxt.ai%3Fw%3D1678%26dpr%3D2" alt="header image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nuxt has recently released a new image optimization module, which allows developers to easily optimize their images within Nuxt without having to install additional third party libraries.  I was so happy to have been able to collaborate with the Nuxt Image project by adding full support for imgix and all of imgix's API parameters to the Nuxt Image component.  It was back in October 2020 that I started by contributing to the project to add imgix as a provider. Over the last year I have been able to improve that by adding full support of all of imgix's APIs and providing examples and tutorials in the documentation. I am culminating the experience with this blog.&lt;/p&gt;

&lt;p&gt;This blog will show you some great examples of how you can set up and use these transformations with &lt;code&gt;&amp;lt;nuxt-img&amp;gt;&lt;/code&gt;. I will end it with a full tutorial of making a simple responsive image gallery as well. I originally wrote a somewhat similar version of this post at the &lt;a href="https://blog.imgix.com/2021/09/14/nuxt-image-component"&gt;imgix Blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use imgix?
&lt;/h2&gt;

&lt;p&gt;You might be initially wondering, why should I use imgix with the Nuxt Image component? Nuxt is already including an open-source module to optimize my images.  Yes, the IPX instance included with Nuxt Image is a good module to help optimize locally hosted images.  Here are some great reasons why you should use imgix instead:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;imgix empowers developers with 120+ API transformations for their images.&lt;/li&gt;
&lt;li&gt;No need to edit the images beforehand, you can do that all with imgix.&lt;/li&gt;
&lt;li&gt;Using an open-source image module will also increase your build time with Nuxt, since the images are being processed during the build.&lt;/li&gt;
&lt;li&gt;imgix can also simplify your image management needs. We connect to wherever your images are stored, like an S3 or GCS bucket, and we will provide a UI or API to easily organize and access those images.&lt;/li&gt;
&lt;li&gt;imgix includes global CDN delivery with a custom Fastly instance.
&lt;/li&gt;
&lt;li&gt;imgix has a free tier, so even if you have a small project you are working on you can get access to all of these imgix features with that &lt;a href="https://imgix.com/pricing"&gt;free tier&lt;/a&gt;!
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will certainly supercharge your website or project beyond what is initially offered with the include IPX instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation steps
&lt;/h2&gt;

&lt;p&gt;In order to use the Nuxt Image Component you will need to install it in your already created Nuxt project.  If you would like to see the complete installation instructions, you can view them at &lt;a href="https://image.nuxtjs.org/getting-started/installation/"&gt;Nuxt's Website&lt;/a&gt;. If you are making a new Nuxt project from scratch, during the Nuxt project installation you will see an option to add Nuxt Image easily.  In the instructions below, I am assuming you already have an existing Nuxt project, or you have recently created one, that is going to be statically hosted.  First, you will need to install the Nuxt Image component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; @nuxt/image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you need to add the newly installed devDependency to your nuxt.config.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;target:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'static'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;buildModules:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;'@nuxt/image'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you will need to configure an image section in the nuxt.config.js with your imgix domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;image:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;imgix:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;baseURL:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://tom.imgix.net"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using the &lt;code&gt;&amp;lt;nuxt-img&amp;gt;&lt;/code&gt; Tag with imgix
&lt;/h2&gt;

&lt;p&gt;You can now replace &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags with &lt;code&gt;&amp;lt;nuxt-img&amp;gt;&lt;/code&gt; tags.  You would select imgix as the provider, add the image path name to the src tag, and then have the ability to add additional props to further optimize your images.  Here is a typical example that you can also find in the Nuxt Image documentation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nuxt-img&lt;/span&gt;
  &lt;span class="na"&gt;provider=&lt;/span&gt;&lt;span class="s"&gt;"imgix"&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/blog/woman-hat.jpg"&lt;/span&gt;
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt;
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt;
  &lt;span class="na"&gt;fit=&lt;/span&gt;&lt;span class="s"&gt;"cover"&lt;/span&gt;
  &lt;span class="na"&gt;:modifiers=&lt;/span&gt;&lt;span class="s"&gt;"{ auto: 'format,compress', crop: 'faces' }"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would result in a 300 x 500 image, that has optimized the format depending on a browser, is automatically being compressed, and intelligently cropping to the face of the image.  Here is the resulting url: &lt;a href="https://assets.imgix.net/blog/woman-hat.jpg?w=300&amp;amp;h=500&amp;amp;fit=crop&amp;amp;crop=faces&amp;amp;auto=format,compress"&gt;https://assets.imgix.net/blog/woman-hat.jpg?w=300&amp;amp;h=500&amp;amp;fit=crop&amp;amp;crop=faces&amp;amp;auto=format,compress&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Responsive Design with Nuxt Image
&lt;/h2&gt;

&lt;p&gt;A more complex example would be using the sizes attribute to build out a responsive design. If you would like to create an image gallery, that is set up as columns and uses a responsive design to become full width on mobile, you can actually pass this in the sizes attribute and Nuxt will generate the appropriate size image for each media width.  Adding something like this would generate a responsive srcset in an image tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nuxt-img&lt;/span&gt;
  &lt;span class="na"&gt;provider=&lt;/span&gt;&lt;span class="s"&gt;"imgix"&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/blog/woman-hat.jpg"&lt;/span&gt;
  &lt;span class="na"&gt;fit=&lt;/span&gt;&lt;span class="s"&gt;"crop"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"sm:100vw md:100vw lg:50vw xl:33vw"&lt;/span&gt;
  &lt;span class="na"&gt;:modifiers=&lt;/span&gt;&lt;span class="s"&gt;"{ auto: 'format,compress', crop: 'faces,edges', ar: '1:1' }"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A good tip here, even though my small and medium sizes are going to both be 100vw, you should enter them both.  The more size options you add, the more sizing options that will be available in your resulting srcset.  Also remember, with imgix, you have an unlimited amount of renders with all of your images, so there is no reason why you shouldn't include many resizing options to ensure you always have the best size image being loaded on your website.  &lt;/p&gt;

&lt;p&gt;You might have noticed some additional items that I included in the modifiers compared to my first example.  I added an &lt;code&gt;ar: 1:1&lt;/code&gt; to the modifier.  This will crop all of my images to a square.  You might at first be concerned that I am going to crop all of my images. I have actually also modified my crop request to be &lt;code&gt;faces,edges&lt;/code&gt;.  So if an image is not a square and I end up cropping portions of the image, I will ensure that I do not crop out any faces. If there are no faces, then the image will focus on the prominent edges in the picture as well.  &lt;/p&gt;

&lt;p&gt;Here is an example of the resulting image tag from the above nuxt-img:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; 
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://assets.imgix.net/blog/woman-hat.jpg?auto=format,compress&amp;amp;amp;crop=faces&amp;amp;amp;ar=1:1&amp;amp;amp;w=397&amp;amp;amp;fit=crop"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 640px) 98vw, (max-width: 768px) 98vw, (max-width: 1024px) 49vw, 31vw"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"https://assets.imgix.net/blog/woman-hat.jpg?auto=format,compress&amp;amp;crop=faces,edges&amp;amp;ar=1:1&amp;amp;w=627&amp;amp;fit=crop 627w, https://assets.imgix.net/blog/woman-hat.jpg?auto=format,compress&amp;amp;crop=faces,edges&amp;amp;ar=1:1&amp;amp;w=753&amp;amp;fit=crop 753w, https://assets.imgix.net/blog/woman-hat.jpg?auto=format,compress&amp;amp;crop=faces,edges&amp;amp;ar=1:1&amp;amp;w=502&amp;amp;fit=crop 502w, https://assets.imgix.net/blog/woman-hat.jpg?auto=format,compress&amp;amp;crop=faces,edges&amp;amp;ar=1:1&amp;amp;w=397&amp;amp;fit=crop 397w"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that it has generated four different versions in the srcset, each with a different size. This allows the browser to choose an image that is closest to the rendered resolution of the image. This helps to ensure you have many image options to be loaded for a good responsive design.&lt;/p&gt;

&lt;p&gt;Furthermore, since we are using &lt;code&gt;auto=format&lt;/code&gt;, imgix will automatically choose the best image format based on the viewer's browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image Gallery Tutorial
&lt;/h2&gt;

&lt;p&gt;In this tutorial, I am going to be creating a simple image gallery in a Nuxt project.  I will also be using Tailwind CSS and be deploying this site on Vercel.  The image gallery will be a flex design, with 3 columns on the largest screen sizes, 2 columns on the smaller desktop sizes, and 1 column on mobile sizes.  The images will be using the Nuxt Image component and will contain a responsive design.  If you would like to skip the tutorial and go right to the code, you can see that in &lt;a href="https://github.com/daletom/nuxt-image"&gt;Github&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Please start by &lt;a href="https://nuxtjs.org/docs/2.x/get-started/installation#using-create-nuxt-app"&gt;initiating a Nuxt project&lt;/a&gt; and during the setup steps you will see an option to include Nuxt Image in this new project.  When initiating the Nuxt project, I would suggest choosing Tailwind CSS, since my examples will be using this module for css.&lt;/p&gt;

&lt;p&gt;Once the project is initiated, don't forget to go to your &lt;code&gt;nuxt.config.js&lt;/code&gt; to enable imgix as the Nuxt Image solution, as per the instructions at the beginning of this blog.  Now that everything is all set up, go to your index.vue file in your pages folder.  Erase what is currently there and start fresh with a div tag.  Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can add some sections for a headline and text at the top of your page.  Here is an example of adding this with some Tailwind CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title-font sm:text-4xl text-3xl m-4 font-medium text-gray-900"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Example using the Nuxt Image Component&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"m-4 leading-relaxed"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Optimize your images with imgix in your Nuxt Image Component.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we can focus on adding a flex div to include your images and the nuxt-img tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title-font sm:text-4xl text-3xl m-4 font-medium text-gray-900"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Example using the Nuxt Image Component&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"m-4 leading-relaxed"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Optimize your images with imgix in your Nuxt Image Component.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-wrap"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;nuxt-img&lt;/span&gt;
        &lt;span class="na"&gt;provider=&lt;/span&gt;&lt;span class="s"&gt;"imgix"&lt;/span&gt;
        &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
      &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can add as many images inside of the flex div as we would like for our gallery.  For the next code example, I will focus on just the &lt;code&gt;&amp;lt;nuxt-img /&amp;gt;&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nuxt-img&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"float-left p-2 m-auto w-full lg:w-1/2 xl:w-1/3 2xl:w-1/3"&lt;/span&gt;
  &lt;span class="na"&gt;provider=&lt;/span&gt;&lt;span class="s"&gt;"imgix"&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"xs:98vw sm:98vw md:98vw lg:49vw xl:31vw 2xl:31vw"&lt;/span&gt;
  &lt;span class="na"&gt;fit=&lt;/span&gt;&lt;span class="s"&gt;"crop"&lt;/span&gt;
  &lt;span class="na"&gt;:modifiers=&lt;/span&gt;&lt;span class="s"&gt;"{ auto: 'format,compress', ar: '1:1' }"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have included in 2 places info about the sizing that will help my responsive design. First, in the class section.  Again, just a reminder, this is an example of using Tailwind CSS. If this is your first time encountering it, I really do suggest checking out their &lt;a href="https://tailwindcss.com/docs"&gt;documentation&lt;/a&gt;.  On XL and 2XL size screens, the images will be viewed in css at 33% the size of the screen. Between 1024 px and 1280 px size screens, the images will be viewed in css at 50% the size of the screen. Then any screen smaller than 1024px wide will be viewed at 100% the size of the screen.  I have also replicated this same idea in the &lt;code&gt;sizes&lt;/code&gt; attribute, which tells the Nuxt Image Component to generate resized versions for each of these scenarios. It's so important to match your css design with the sizes in the img tag, that way images are being loaded in at the correct size.&lt;/p&gt;

&lt;p&gt;Now, you can go ahead and create as many of these &lt;code&gt;&amp;lt;nuxt-img&amp;gt;&lt;/code&gt; tags as you need for your gallery.  If you are going to pass image urls from data or an API, you can easily use the v-for attribute as well.  I do believe this is one of the more powerful aspects of Nuxt, so I will go ahead and add 6 image names in my Data section and pass them as a v-for.  &lt;/p&gt;

&lt;p&gt;For my list of images, they are conveniently named 1 through 6, so I will place them in my &lt;code&gt;script&lt;/code&gt; section of my index.vue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/artsy/1.jpg?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/artsy/2.jpg?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/artsy/3.jpg?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/artsy/4.jpg?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/artsy/5.jpg?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/artsy/6.jpg?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can now access these images using a v-for in my &lt;code&gt;&amp;lt;nuxt-img&amp;gt;&lt;/code&gt;.  In order to do that, here is how I am modifying my tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nuxt-img&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"float-left p-2 m-auto w-full lg:w-1/2 xl:w-1/3 2xl:w-1/3"&lt;/span&gt;
  &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(image, index) in images"&lt;/span&gt;
  &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;
  &lt;span class="na"&gt;provider=&lt;/span&gt;&lt;span class="s"&gt;"imgix"&lt;/span&gt;
  &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"xs:98vw sm:98vw md:98vw lg:49vw xl:31vw 2xl:31vw"&lt;/span&gt;
  &lt;span class="na"&gt;fit=&lt;/span&gt;&lt;span class="s"&gt;"crop"&lt;/span&gt;
  &lt;span class="na"&gt;:modifiers=&lt;/span&gt;&lt;span class="s"&gt;"{ auto: 'format,compress', ar: '1:1' }"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will loop through my 6 images, creating a responsive img tag for each of them in my gallery.  This is a rather simple idea of using a v-for, but hopefully gives you the idea of how quickly this can be used on a large amount of images.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying Your Nuxt Project
&lt;/h2&gt;

&lt;p&gt;I will be pushing this project up to Github using Github Desktop.  Once you have pushed your project to Github, you can then deploy it.  For this example, I will be using Vercel.  One thing I do to ensure my Vercel builds go smoothly with Vercel is to create a vercel.json file and add a builds section.  Mine looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"builds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nuxt.config.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@nuxtjs/vercel-builder"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you would like to go one step further with an advanced item the imgix and Vercel do well together, it would be setting up &lt;a href="https://docs.imgix.com/apis/rendering/format/ch"&gt;Client Hints&lt;/a&gt; on these images.  Client Hints will tell imgix the exact width and dpr of an image in a Chrome browser, allowing imgix to provide the perfect size every time. This solution only works with Chrome browsers, but it's a great item to still use in conjunction with another responsive set up like this.  If you look at the documentation, you might notice a warning about Chrome not supporting sending Client Hints to third-party origins.  Well Vercel solves that by confirming the routes and feature policy in the vercel.json file, so it is no longer a third-party origin.  Here is what you add to to vercel.json file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Accept-CH"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DPR, Width, Viewport-Width"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Feature-Policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ch-dpr https://tom.imgix.net 'self'; ch-width https://tom.imgix.net 'self'; ch-viewport-width https://tom.imgix.net 'self'"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the place of the imgix domain I am using for this example, enter your imgix domain.  Finally, I used the Vercel for Github integration, which quickly launches my website from an repos in my Github account.&lt;/p&gt;

&lt;p&gt;Here is a link to the &lt;a href="https://nuxt-image.vercel.app/"&gt;live tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is a pretty simple tutorial example of how you can use imgix with the new Nuxt Image Component, but I hope it has been helpful for you.  I was so excited to be a part of the process of having imgix and all of the APIs added to the Nuxt Image component early in the process.  It is a really simple way to create a responsive design directly inside Nuxt while also getting access to a very powerful image solution from imgix.  If you would like to see more advanced versions of this tutorial, or possibly examples from other data sources like a headless CMS or other API, I would love to hear all of your requests.  Please don't hesitate to comment or reach out to me on &lt;a href="https://twitter.com/letsgoheadless"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>responsive</category>
      <category>tutorial</category>
      <category>imgix</category>
      <category>nuxt</category>
    </item>
    <item>
      <title>Headless Shopify with Nuxt, Tailwind, imgix, &amp; Vercel</title>
      <dc:creator>Tom Dale</dc:creator>
      <pubDate>Wed, 26 May 2021 00:30:20 +0000</pubDate>
      <link>https://dev.to/daletom/headless-shopify-with-nuxt-tailwind-imgix-vercel-1ldg</link>
      <guid>https://dev.to/daletom/headless-shopify-with-nuxt-tailwind-imgix-vercel-1ldg</guid>
      <description>&lt;p&gt;People have started to realize that their tried and true traditional eCommerce platforms  are falling behind when it comes to performance.  I wanted to take a look at a particularly popular eCommerce tool with a lower cost barrier, Shopify.  Shopify does a lot of things well.  Shopify can be a simple tool to manage your products, from price, to images, to inventory.  It also does a good job with the checkout process.  It has always offered website templates to easily deploy your site on a Shopify front end.  It reminds me of a simpler setup than even using a Wordpress template.  But when you deploy your eCommerce Website using Shopify, you are often sacrificing on performance for ease of use.  It turns out that Shopify has made it quite easy to access the functionality your Shopify account using an API.  I am going to show an easy method to utilize Shopify's Storefront Access Token in an API with Nuxt.js as the front end. I will also boost performance scores using imgix for the images and Vercel to host the site.&lt;/p&gt;

&lt;h3&gt;
  
  
  Goals For What We Are Building
&lt;/h3&gt;

&lt;p&gt;My goal for this demo is to quickly create a working headless eCommerce website using Shopify. In the end we will have a simple page is displaying three products, with their name and description, all coming from the Shopify API.  We will be accessing the Shopify API via a nuxt-shopify SDK, which is essentially a GraphQL API.  This way you can request information specific to a product or category, without having to request all info via the API on every page request.  This will be set up in Nuxt as the front-end, but will be displayed via Vercel using SSR. This allows end users to modify/add/remove products all in the Shopify UI and have those changes be immediately reflected on the website without having to push or deploy any changes via a webhook.  Here are links if you would like to jump ahead to the &lt;a href="https://github.com/daletom/headless-shopify-test01" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. If you would prefer to follow along in a video, here is the demo on Youtube:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/vI_JpzCTUX8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Items
&lt;/h2&gt;

&lt;p&gt;Run the following command to start a nuxt project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init nuxt-app "projectname"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will provide you a list of items to fill out in your terminal to create your project.  I am using Javascript, choose your package manager, Tailwind CSS as my UI framework, I do not need any of these additional modules, choose the LINTER of your choice, no testing framework, a Universal rendering mode, and Static hosting.  The final two there are important to do, the rest you can change or modify as you wish. &lt;/p&gt;

&lt;p&gt;We will also need to install two other items. This is the nuxt/shopify SDK and the vue-imgix SDK.  I will cover these items in more detail below as we utilize them&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install nuxt-shopify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the vue-imgix SDK&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install vue-imgix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sign up for Shopify and get Storefront Access Token
&lt;/h2&gt;

&lt;p&gt;Next you will need to create a Shopify account.  They do offer a free test for __ days to build and test your Shopify account.  Go to Shopify's Sign Up page to create your account now if you don't have one.&lt;/p&gt;

&lt;p&gt;After you have completed signing up or logging in to your existing account, we will now need to get access to the Storefront Access Token.  A lot of examples on the internet made this seem difficult, but it's actually quite easy.  You just need to create a new developer app by clicking apps on the left menu, then clicking a hard to see link called manage private apps.  Here is a screenshot of where it is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbtcvbg3v6dzrrcpexkhp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbtcvbg3v6dzrrcpexkhp.png" alt="New Shopify Developer App"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fill out the form, for the Storefront API Permissions you will want to check off all of these.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgvn72883s5u6e928psr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgvn72883s5u6e928psr.png" alt="Access for new app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this is completed, you can scroll down and see a field called Storefront Access Token.  It's import to use this token, not the Shopify API token.  Now go ahead and go to your Nuxt project that you created.  Create a .env file in the base of your project.  I went ahead and added variables for my store's Shopify url and the storefront token. Your .env file will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOPIFY_DOMAIN="letsgoheadless.myshopify.com"
SHOPIFY_ACCESS_TOKEN="1234"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will want to update the nuxt.config file to finalize the connection to your Shopify account.  In the modules section of your nuxt.config, you will want to add nuxt-shopify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;modules: ['nuxt-shopify'],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you will want to add a section called shopify.  You will add the process.env for your domain and storefront token here. Also add true to unoptimized.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shopify: {
    domain: process.env.SHOPIFY_DOMAIN,
    storefrontAccessToken: process.env.SHOPIFY_ACCESS_TOKEN,
    unoptimized: true
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will now have access to items in your Shopify Account.  If you created a new Shopify account during this demo, you will then need to add a couple products to your account so we have something to look at.  If you want to see an example of me adding products, you can refer back to the video link above, at minute 13:58. If you already have an account, we can move forward from here.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Displaying Data from Shopify
&lt;/h2&gt;

&lt;p&gt;Now that we have correctly connected to Shopify using our Storefront Access Token and we have added a few products to our Shopify accounts, let's at least prove that we can display json results from an API call.  Let's go to our index.vue page, which is our home page. I'm going to add a fetch request using the nuxt-shopify sdk in the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; portion at the bottom of our index.vue page.  I am adding this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
  async asyncData({ $shopify, params }) {
      const products = await $shopify.product.fetchAll();
      return { products };
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I got this fetchAll request from the &lt;a href="https://nuxt-shopify-docs.vercel.app/" rel="noopener noreferrer"&gt;nuxt-shopify sdk page&lt;/a&gt;. You can see there are a lot of examples of the various requests you can make here.  Now, I want to create a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; list and display the json data here.  In this list, I need to be sure to do a v-for and a key to make the api call.  Since I returned the fetchAll as products, I will do a v-for for that.  Here is what I am adding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ul class="mt-4 text-center"&amp;gt;Shopify JSON response
      &amp;lt;li v-for="product in products" :key="product.id"&amp;gt;
        {{product}}
      &amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the v-for, I renamed the products to product and I am using the id value as a key to bind them.  So theoretically if I simply put product inside of double curly brackets, it will display the entire json result of all of the products I am fetching from Shopify.  If you run &lt;code&gt;npm run dev&lt;/code&gt; in your console now, you should see the json response.  This is an example of what a portion of mine looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzY3ODcxMjE1NzgxNTA=", "availableForSale": true, "createdAt": "2021-05-21T18:06:37Z", "updatedAt": "2021-05-21T19:45:51Z", "descriptionHtml": "Blue Hoodie everyone will need to have", "description": "Blue Hoodie everyone will need to have", "handle": "blue-hoodie", "productType": "", "title": "Blue Hoodie", "vendor": "letsgoheadless", "publishedAt": "2021-05-21T18:07:04Z", "onlineStoreUrl": null, "options": [ { "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0T3B0aW9uLzg3NTc3OTk2MTY2Nzg=", "name": "Title", "values": [ { "value": "Default Title", "type": { "name": "String", "kind": "SCALAR" } } ], "refetchQuery": {}, "type": { "name": "ProductOption", "kind": "OBJECT", "fieldBaseTypes": { "id": "ID", "name": "String", "values": "String" }, "implementsNode": true } } ], "images": [ { "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0SW1hZ2UvMjkxMjMxMzM2MzY3NzQ=", "src": "https://cdn.shopify.com/s/files/1/0568/1833/5910/products/ix_blue_hoodie.png?v=1621620398", "altText": null, 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will notice that you will see the name, description, images, and any other data you have entered.  If you entered multiple images for each product, there will be multiple images in the images section.  Since there potentially will be multiple images in the future, I would like to now focus on calling the first image which is the primary image for the product.  I would also like to see the src url for each image.  In order to do that, I am now going to modify the product I had entered, to now view the first image, which is displayed by a 0, followed by src.  So here is the updated list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ul class="mt-4 text-center"&amp;gt;Shopify JSON response
      &amp;lt;li v-for="product in products" :key="product.id"&amp;gt;
        {{product.images[0].src}}
      &amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should now display the Shopify url for each of these images in a list.  That's great, we can now easily call the image urls of the Shopify images!  If you remember, I did say I was using Tailwind CSS with my Nuxt project when we initialized it.  So if you aren't familiar with Tailwind, the items I put in the class of an element is the style I am adding.  So the &lt;code&gt;mt-4 text-center&lt;/code&gt; I added in the list class, is a margin of 4 and centering the text.  I'm not going to explain much more about the Tailwind elements I am using, but certainly welcome you to check out more about Tailwind if you don't feel that you are great at css, because Tailwind makes it so much easier.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Outlining Our Product Component
&lt;/h2&gt;

&lt;p&gt;Now that we know how to get specific data about each of our products, let's create a simple product component and display them.  I am going to create a &lt;code&gt;ProductWidget.vue&lt;/code&gt; in the components folder in our nuxt project.  Then I'm going to create a couple of divs to display the image, title, and description of each product:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="rounded-t-lg bg-grey pt-2 pb-2"&amp;gt;
            &amp;lt;img :src="product.images[0].src"
                class="crop mx-auto"
                width="380"
                height="380"
                loading="lazy"
            /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class="pl-4 pr-4 pb-4 pt-4 rounded-lg"&amp;gt;
            &amp;lt;h4 class="mt-1 font-semibold text-base leading-tight truncate text-gray-700"&amp;gt;
                {{product.title}}
            &amp;lt;/h4&amp;gt;
            &amp;lt;div class="mt-1 text-sm text-gray-700"&amp;gt;{{product.description}}&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see I used the same product.images[0].src for the img src, but remember to add a &lt;code&gt;:&lt;/code&gt; to src, so it will bind correctly.  For the title and description, they are just simply product.title or description.  I am also going to update the script at the bottom of this component in order to identify product in the props and provide a name for the component to call on the index.vue page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
        name: 'productWidget',
        props: {
            product: {
                type: Object,
                default: null
            }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in order to make this component to work on the index.vue page, we are going to need to import the component and register it. I have updated my script like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script&amp;gt;
import ProductWidget from '~/components/ProductWidget.vue'
export default {
  name: "IndexPage",
  components: {
    ProductWidget
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am now going to add a div above my Shopify Json response list that will contain the component. I need to add the v-for and :key again like we did earlier for this div. I am also going to add a v-bind to allow me to use the product inside of the component. Here is what I did:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;div class="m-6 grid grid-cols-1 2col:grid-cols-2 3col:grid-cols-3 gap-4"&amp;gt;
      &amp;lt;div v-for="product in products" :key="product.id" v-bind:product="product" class="border rounded-lg bg-gray-100 hover:shadow-lg"&amp;gt;
        &amp;lt;productWidget :product="product"&amp;gt;&amp;lt;/productWidget&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maybe you noticed the div I added with all of the tailwind css references in the class. That is how I will be using a grid with Tailwind.  One unique item I did here was to actually customize my Tailwind setup, choosing at certain breakpoints whether to have 1, 2, or 3 columns.  If you are wanting to up your Tailwind game, this is how I adjusted those sizes and created the custom 2col and 3col names. I created a tailwind.config.js file and added this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
    theme: {
        screens: {
            '2col': '850px',
            '3col': '1290px',
        },
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, now if you refresh your localhost again in the browser, you should be seeing several products.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing the images
&lt;/h2&gt;

&lt;p&gt;Now that you are looking at your products, you might have noticed the images aren't really optimized, and maybe they might look a little odd next each other because they all have different aspect ratios.  I am going to address that by using imgix to optimize these images.  Just to confirm, I have been working at imgix since 2015, so I do like using imgix for my projects. You can certainly use another optimization service as well. This isn't a post sponsored by imgix, I just happen to be someone that works at imgix that is writing this post at night on my own time. &lt;/p&gt;

&lt;p&gt;Now that we got that out of the way :) I need to essentially cname my shopify image urls to my imgix account. I can do that by creating a web folder source and pointing it to the shopify urls of my images.  These are what my images look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://cdn.shopify.com/s/files/1/0568/1833/5910/products/ix_blue_hoodie.png?v=1621620398
https://cdn.shopify.com/s/files/1/0568/1833/5910/products/ix_holo_sticker.jpg?v=1621620474
https://cdn.shopify.com/s/files/1/0568/1833/5910/products/ix_gamer_jersey.png?v=1621620521
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of the product image urls are the same up to the point after the account id and products.  So if I cname up to that portion, I can replace it with my imgix url and start optimizing those images.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9mp62jgh4b2cmeu7lxs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9mp62jgh4b2cmeu7lxs.png" alt="imgix webfolder setup for Shopify"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now those urls could be this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://headless-shopify.imgix.net/ix_blue_hoodie.png
https://headless-shopify.imgix.net/ix_holo_sticker.jpg
https://headless-shopify.imgix.net/ix_gamer_jersey.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to programmatically change these urls and add responsive design and optimization, I can use that vue-imgix SDK we installed in the beginning.  Since this is more of a natively Vue SDK, we will need to create a file in the plugins folder to make it work on Nuxt.  I am calling this file vue-imgix.js, this is what I put in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Vue from 'vue';
import VueImgix from 'vue-imgix';

Vue.use(VueImgix, {
    domain: "headless-shopify.imgix.net",
    defaultIxParams: {
        auto: 'format,compress'
    },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose whatever domain you are using. I am also using auto format,compress as my default, which will just apply some smart formatting and compression.  If the compression is too much for your nicer ecomm images, just remove the compress.  The format will not hurt your image quality, so definitely always use that at least. Now just register the plugin in the nuxt.config file like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins: ['~/plugins/vue-imgix.js'],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can go back to our ProductWidget component and adjust the img tag.  Now you can update this to a ix-img tag, which will start using the vue-imgix sdk.  I am going to keep the images at a fixed size of 380, but add in multiple sizes for each device resolution.  I am also going to add some imgix parameters that will try to fit everything to the same size without cropping, filling in any extra space with a color the same as the background. Also, I am trimming away any extra space around the image, again, without cropping a part of the product.  Here is what my img tag now looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ix-img :src="product.images[0].src"
                class="crop mx-auto"
                width="380"
                height="380"
                :imgixParams="{fit:'fill', fill:'solid', fillcolor:'f7fafc', trim:'auto'}"
                loading="lazy"
                fixed
            /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try to look at the images now, they will be broken. That is because the src is still calling the shopify image url, but I am also adding my imgix domain in front of the entire shopify image url.  I need to remove the characters from that url that I identified in my webfolder source.  I also want to remove the v= characters at the end of the url.  In order to do that, I am going to create a method called imageSrc.  Then I will just use a slice to remove the beginning and ending characters of the shopify url that we are receiving.  So if I slice the first 57 characters, and slice the last 13 characters, that will get me just the file name ix_blue_hoodie.png. So however many characters you need to slice, you should do on your end as well. Here is my method I built in the ProductWidget component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;methods: {
   imageSrc() {
     return this.product.images[0].src.slice(57, -13)
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now instead of the product.images[0].src, I can call imageSrc() in the src of the img tag.  Here is the final img tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ix-img :src="imageSrc()"
                class="crop mx-auto"
                width="380"
                height="380"
                :imgixParams="{fit:'fill', fill:'solid', fillcolor:'f7fafc', trim:'auto'}"
                loading="lazy"
                fixed
            /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will see the images will work, they look similar, are all automatically trimmed, good quality, and performant!  &lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Deploy
&lt;/h2&gt;

&lt;p&gt;We are on the home stretch. So I am going to choose to deploy on Vercel. I like how easy it is to deploy SSR with Vercel. In order to do that, I created a vercel.json file and added this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "builds": [
        {
        "src": "nuxt.config.js",
        "use": "@nuxtjs/vercel-builder",
        "config": {}
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can just commit this all to your Github account. Then log in to Vercel, import a new project from that Github account. While you are in the process of deploying the site on Vercel, the last item you need to do is to add the items you put in your .env file into the variables section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mj7i5z6impvzkxjftoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mj7i5z6impvzkxjftoc.png" alt="Add Environment Variables in Vercel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These would be the Storefront API tokens and shopify domain. You can just copy the values from there and enter them in Vercel. Just don't enter the values with a "" around them, that is not needed in Vercel.  Press deploy and soon you should be seeing Vercel's fireworks, your site is up and running using headless Shopify!  &lt;/p&gt;

&lt;p&gt;Don't hesitate to comment or reach out if you have questions. I think the video recording can be very helpful to go along with this explanation. Would love to see anything you are all working on as well.&lt;/p&gt;

</description>
      <category>nuxt</category>
      <category>webdev</category>
      <category>headless</category>
      <category>ecommerce</category>
    </item>
    <item>
      <title>Optimizing Images with Next.JS &amp; Vercel</title>
      <dc:creator>Tom Dale</dc:creator>
      <pubDate>Thu, 05 Nov 2020 14:35:00 +0000</pubDate>
      <link>https://dev.to/daletom/optimizing-images-with-next-js-vercel-3m3n</link>
      <guid>https://dev.to/daletom/optimizing-images-with-next-js-vercel-3m3n</guid>
      <description>&lt;p&gt;Did you hear!? &lt;a href="https://nextjs.org/blog/next-10#images-on-the-web" rel="noopener noreferrer"&gt;Next.js version 10&lt;/a&gt; now includes image optimization! All of you have to do is switch an image tag, import one line, and add your height and width in that tag.  Is it that easy? What's really happening here?  These are all the questions I will answer while giving you an example template and showing you the results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Dive In and Clone a Next.js Project
&lt;/h2&gt;

&lt;p&gt;If you want to follow along, just enter this in your terminal to clone the next.js starter I have for this image optimization example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app nextjs-imgopt --use-npm --example "https://github.com/daletom/nextjs-imgblog"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then go into the project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd nextjs-imgopt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then you might need to install the dependencies &lt;code&gt;npm install&lt;/code&gt; or fix some outdated items &lt;code&gt;npm audit fix&lt;/code&gt;. Now you can run the site in development&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and go to your &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;localhost&lt;/a&gt; to see it in action.&lt;/p&gt;

&lt;p&gt;Here is a completed example if you just want to skip to the end on &lt;a href="https://github.com/daletom/nextjs-imgblog" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or the live url on &lt;a href="https://nextjs-imgblog.vercel.app/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Can I Tell These Images are Optimized?
&lt;/h2&gt;

&lt;p&gt;Great question! I would suggest viewing this in Chrome or Firefox for the dev tools. I'm right clicking on one of the images and selecting inspect in my Chrome. The dev tools should open and you should see something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flan4953fhehq1tn95ckc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flan4953fhehq1tn95ckc.png" alt="Dev Tools Inspect Showing Src Sets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is showing a several &lt;code&gt;srcsets&lt;/code&gt; of an image, 320 wide, 420 wide, 768 wide, etc. This is a list of various sizes of each image that the browser can choose to load  as the image. You will also notice several &lt;code&gt;data-srcsets&lt;/code&gt; as well. Those are generated because we are also lazy loading these images. The browser is actually using the sizes attribute to determine which size image it loads. You can be smart with sizes and declare various sizes depending on the size of your browser window which allows Chrome to select various srcsets for many different browser/device sizes viewing your images.&lt;/p&gt;

&lt;p&gt;Another great way to tell if they are getting optimized?  Look at the format of the image. If you are on a Chrome or Firefox browser, you will notice they are webp. Yep, these images are intelligently being formatted to webp!&lt;/p&gt;

&lt;p&gt;Wondering which size of an image is being loaded? When you are inspecting, you can hover over a srcset and it will show a little preview of the image:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9uh9oxm7s95f2efpwb8k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9uh9oxm7s95f2efpwb8k.png" alt="Preview of image in dev tools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This shows the image is being viewed on the browser at a certain size (254 x 191 pixels) but the intrinsic value is the actual size of the image being loaded (yep, from srcset). This example is loading 420 x 315 pixels. I am fine with that, Chrome is being smart and increasing the size because I am on a MacBook Pro which has a screen with a high device pixel ratio (DPR). So Chrome is adding this larger option to ensure the image looks crisp on my screen.&lt;/p&gt;

&lt;p&gt;These are all great examples of good image optimization practices. Adding various &lt;code&gt;srcset&lt;/code&gt; options for images, intelligent image formatting, declaring a sizes attribute to help with responsive design, lazy loading, and serving larger images to higher DPR devices. It sounds like a lot, but I actually barely did anything in the Next.js code to make this all happen!&lt;/p&gt;
&lt;h2&gt;
  
  
  How did the Image Optimization Get Added?
&lt;/h2&gt;

&lt;p&gt;So we did a bunch of great image optimization items, but how did I do it? Instead of using an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; in your projects, you can drop in &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt; instead.  All you have to do is reference it with this line (I did this in my pages/index.js):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Image from 'next/Image'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then replace the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; with &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt;. In the examples for this project, I am using a local image in the public folder. I then added a large width and height that met the aspect ratio I needed.  Why a large width and height? It generates additional &lt;code&gt;srcsets&lt;/code&gt; for the image, which is great because I am going to add a sizes attribute that matches the design of my site. I have added &lt;code&gt;loading="lazy"&lt;/code&gt;, which uses Chrome/Firefox's Native lazy loading. Then a low quality of 35. Don't worry, 35 isn't a % of 100, it's a lower setting that is fine for a blog. If you are doing high fashion, maybe make it a 70 :)&lt;/p&gt;

&lt;p&gt;Lets see the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Image
  src="/images/terrarium.jpg"
  alt="Terrarium"
  width={1600}
  height={1200}
  loading="lazy"
  quality={35}
  sizes="(max-width: 600px) 100vw, (max-width: 1023px) 48vw, 23vw"
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What was that in the Sizes Attribute?
&lt;/h2&gt;

&lt;p&gt;I know, I quickly skimmed over the &lt;code&gt;sizes&lt;/code&gt; attribute. But I was on a roll and I couldn't stop! What I'm doing is essentially telling the browser to find an image in the &lt;code&gt;srcset&lt;/code&gt; that closely meets these scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if the browser is smaller than 600 pixels wide, find an image that is 100% the width of the browser&lt;/li&gt;
&lt;li&gt;if the browser is between 601 px and 1023 px wide, find an image that is 48% the width of the browser&lt;/li&gt;
&lt;li&gt;if the browser is larger than 1024 px, find an image that is 23% the width of the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is an example of 4 columns in larger desktop, shifting to 2 columns, shifting to 1 single column on mobile. This is what the corresponding css looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.column {
  flex: 23%;
  max-width: 23%;
  padding: 0 4px;
}

@media screen and (max-width: 1023px) {
    .column {
      flex: 48%;
      max-width: 48%;
    }
  }
@media screen and (max-width: 600px) {
    .column {
      flex: 100%;
      max-width: 100%;
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How much better are these Optimized Images?
&lt;/h2&gt;

&lt;p&gt;So glad you asked. I actually included a link to a second page of &lt;a href="https://nextjs-imgblog.vercel.app/unopt" rel="noopener noreferrer"&gt;unoptimized images&lt;/a&gt; that mirrors the 8 images and workflow we just did. Without optimizing those same images, they are 18.5 MB compared to 650 KB (depending on which size and type of browser you are on). That is an unbelievable size difference. &lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy to Vercel &amp;amp; Done
&lt;/h2&gt;

&lt;p&gt;I know everything has been pretty easy up to this point and this section is not any different. Use whatever means to get it on something like Github (I use Github desktop). Then import a new project in Vercel, choose this Github project, it will detect it is Next.js, and press deploy! Also, thanks for baring with me while I secretly just shared tons of fun photos of my kids with you all :) Again here is the final &lt;a href="https://nextjs-imgblog.vercel.app/" rel="noopener noreferrer"&gt;site&lt;/a&gt; you just made with me.&lt;/p&gt;

</description>
      <category>vercel</category>
      <category>webperf</category>
      <category>nextjs</category>
      <category>responsive</category>
    </item>
    <item>
      <title>Creating a Headless eComm site with Prismic, imgix, Nuxt, &amp; Snipcart</title>
      <dc:creator>Tom Dale</dc:creator>
      <pubDate>Wed, 30 Sep 2020 14:14:22 +0000</pubDate>
      <link>https://dev.to/daletom/creating-an-ecomm-site-with-prismic-imgix-nuxt-snipcart-4n8p</link>
      <guid>https://dev.to/daletom/creating-an-ecomm-site-with-prismic-imgix-nuxt-snipcart-4n8p</guid>
      <description>&lt;p&gt;I recently did a live demo at the Netlify Headless Commerce conference where I built and deployed a simple eComm site in about 10 minutes.  It was such a fun demo I wanted to share the steps here.  The site is using Prismic as a headless CMS, imgix for responsive images, Nuxt.js on the front end, Tailwind as a CSS framework, Snipcart for the shopping cart, and Netlify to deploy the site.  If you want to sign up for these and follow along, I didn't spend one penny to deploy this.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are we building?
&lt;/h3&gt;

&lt;p&gt;My goal for this demo was to quickly create a working eComm website using technology to support Headless Commerce. In the end we will have a simple page that has a Navbar with your company name and shopping cart link, a grid display of all the products on the home page, and an individual page for each product.  Once this is setup in Nuxt, end users can add/remove/edit products easily in Prismic without having to code anything.  The design is pretty bare bones, so you can easily add to this with Tailwind.  Here is a preview of what this will look like:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcvg3080gfwln1nlsc5on.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcvg3080gfwln1nlsc5on.jpg" alt="Preview of Demo Site"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Install Items
&lt;/h2&gt;

&lt;p&gt;Run the following command to install the prismic client (you might need to add sudo):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g prismic-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can clone this theme and initiate the prismic project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prismic theme --theme-url https://github.com/daletom/nuxtjs-ecomm.git --conf nuxt.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Content &amp;amp; Add Snipcart
&lt;/h2&gt;

&lt;p&gt;Next you will need to login to your Prismic Account.  Create a layout and a few products.&lt;br&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftom.imgix.net%2FaddProduct.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftom.imgix.net%2FaddProduct.gif" alt="Upload Example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this is complete, you will need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;login or create a free account at &lt;a href="https://snipcart.com" rel="noopener noreferrer"&gt;Snipcart&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You need to copy the Public Test API Key.  Simply click on your account at the top right and go to API Keys. &lt;/li&gt;
&lt;li&gt;Paste this API key  with an editor.  Now open the project folder we created when you configured the above Prismic theme.  Go to your layouts folder and the default.vue file.  Paste this API key  with an editor.  You will need to replace {your-api-key} with the snipcart API key, it will be in the hidden snipcart div that looks like this:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div hidden id="snipcart" data-api-key="{your-api-key}"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you can return to your terminal and cd into the project folder, then launch your nuxt front end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd {project-name}
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can access it at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Having a look at what I did with images
&lt;/h2&gt;

&lt;p&gt;Now that you are seeing this in your localhost, let's dig in a little more into what we built and why.  If you're following me step-by-step, you may not realize but you also installed the Vue-imgix SDK when you cloned my prismic theme.  This allows us to easily create responsive images in an img or picture element.  For this example, I created a few components and then replaced the &lt;code&gt;img&lt;/code&gt; tag with an &lt;code&gt;ix-img&lt;/code&gt; tag to activate the SDK. If you are looking to add this to your existing Prismic project and are not cloning my theme, here is a simple cheatsheet for adding this to Nuxt:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjgnsqr5bi0q55e033zen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjgnsqr5bi0q55e033zen.png" alt="Vue-imgix SDK cheatsheet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to focus on one of the components I used for the product images, the ProductGallery.vue component.  This is the &lt;code&gt;ix-img&lt;/code&gt; tags I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ix-img
    :src="imageSrc()"
    width="380"
    height="380"
    :imgixParams="{fit:'fill', fill:'solid', fillcolor:'f7fafc', auto:'format'}"
    :alt="imgobject.alt"
    loading="lazy"
    fixed
  /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am using a v-bind for the src of each product. You will notice I am using a &lt;code&gt;imageSrc()&lt;/code&gt; function to build out the image urls.  Since the imgix Vue SDK does not support putting full urls in the ix-img tag, I needed to use this function to remove the pathname.&lt;/p&gt;

&lt;p&gt;I wanted to display each product image at the same size, I feel this will make the gallery of products look better.  This is why I added a width and height of 380.  When I add a width, height, and fixed tag the imgix Vue SDK will make a srcset that is 380x380 at dpr 1, 2, 3, 4, &amp;amp; 5.  &lt;/p&gt;

&lt;p&gt;Since I want all the products to be the same size, 380 x 380, that could result in some cropping and removing part of the product image. I don't want that. Instead, I want to retain all of the image then fill in any extra space with a color in the background of these to match the website (I can do that since these are pngs).  To achieve that with imgix, I can use the fit:'fill', fill:'solid', fillcolor:'f7fafc'. &lt;/p&gt;

&lt;p&gt;The last item about the imgix api I want to mention is the quality settings. When you choose a fixed size that uses different DPRs, you will also notice that the quality settings lower as the dpr numbers increase. This is a great practice with images called variable quality. You can absolutely lower quality further as you increase the dpr of an image.&lt;/p&gt;

&lt;p&gt;I do love that imgix is now serving a large number of variations of images for us now with this SDK.  Now that we have everything in place, here is an example resulting image url.  It is using the prismic image urls, I have my automatic formatting, my set width &amp;amp; height, the fit parameters we discussed, a dpr of 2 since I'm viewing on my mac laptop, a quality of 50, and an identifier for the imgix vue library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://images.prismic.io/tdecomm21/de0680b1-d97e-464b-bc34-0e78a03f1e7c_ix_grey_shirt.png?auto=format&amp;amp;w=380&amp;amp;h=380&amp;amp;fit=fill&amp;amp;fill=solid&amp;amp;fillcolor=f7fafc&amp;amp;dpr=2&amp;amp;q=50&amp;amp;ixlib=vue-2.8.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Launching the project in production
&lt;/h2&gt;

&lt;p&gt;Launching this in Netflify or Vercel is very easy.  I'm using Netlify for this example. When you are ready to launch a production environment, here are the steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run npm run generate in your terminal.  This will generate a dist folder in your project.
&lt;/li&gt;
&lt;li&gt;Connect to Netlify. You can then either connect this project to github and deploy from Netlify or just simply drag the dist folder to &lt;a href="https://www.netlify.com/drop" rel="noopener noreferrer"&gt;NetlifyDrop&lt;/a&gt;.  If connecting from Github, you will be essentially choosing the build command to be npm run generate and the publish directory to be dist.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is a &lt;a href="https://prismic-imgix-nuxt-ecommsample.netlify.app/" rel="noopener noreferrer"&gt;Live Example&lt;/a&gt;. Here is also a video tutorial I did during the Netlify Headless Commerce Conference:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/458013155" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here is the documentation for deploying &lt;a href="https://nuxtjs.org/faq/netlify-deployment/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For Snipcart, you also need to update your storeUrl.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Info about responsive images from &lt;a href="https://www.imgix.com" rel="noopener noreferrer"&gt;imgix&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;If you would like to learn more about the imgix Vue SDK that I used, here is the link to that &lt;a href="https://github.com/imgix/vue-imgix" rel="noopener noreferrer"&gt;SDK&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Snipcart API Key - I know it seems concerning we are adding an API key for Snipcart that could be find in the javascript, but as per Snipcart: 
&amp;gt;"This key can be shared without security issues because it only allows a specific subset of API operations."&lt;/li&gt;
&lt;li&gt;Need more examples from Prismic? Here is a great example on making a &lt;a href="https://user-guides.prismic.io/en/articles/2802125-create-a-sample-blog-with-prismic-and-nuxt" rel="noopener noreferrer"&gt;blog&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Credit
&lt;/h2&gt;

&lt;p&gt;Credit goes to many poeple and the articles they have written for helping and giving insight. Phil Snow, Lucie Haberer &amp;amp; Renaud Bressand from Prismic, as well as Maxime Laboissonniere at Snipcart, and many other folks.&lt;/p&gt;

</description>
      <category>imgix</category>
      <category>headless</category>
      <category>responsive</category>
      <category>cms</category>
    </item>
    <item>
      <title>Client Hints is Back! Deploy with imgix &amp; Vercel</title>
      <dc:creator>Tom Dale</dc:creator>
      <pubDate>Fri, 18 Sep 2020 02:48:27 +0000</pubDate>
      <link>https://dev.to/daletom/client-hints-is-back-deploy-with-imgix-vercel-4abb</link>
      <guid>https://dev.to/daletom/client-hints-is-back-deploy-with-imgix-vercel-4abb</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dg_yTjw7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zo8txfiwo56wy2y0759q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dg_yTjw7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zo8txfiwo56wy2y0759q.jpg" alt="Website Preview of using Client Hints with imgix"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Remember Client Hints?
&lt;/h1&gt;

&lt;p&gt;In 2014 Google Chrome brought us all Client Hints, an exciting way to pass image width and DPR in a browser's request headers.  This made it much easier to serve responsive images by knowing the correct size needed for an image. Except one issue... it caused security concerns and was removed in 2017.  This has been cleared up with the setting of a Feature Policy and you can now use Client Hints again!  Here is some info from &lt;a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/client-hints#responsive_images"&gt;Google&lt;/a&gt; about Client Hints as well.&lt;/p&gt;

&lt;p&gt;Client Hints does work on about &lt;a href="https://caniuse.com/?search=client-hints"&gt;74%&lt;/a&gt; of the web right now.  Is it still worth it?  Yes! Looking back at some previous studies, &lt;a href="https://www.smashingmagazine.com/2016/01/leaner-responsive-images-client-hints/"&gt;Smashing Mag&lt;/a&gt; determined that it saved 19-32% on bandwidth than using predetermined image breakpoints in srcset.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using Client Hints
&lt;/h1&gt;

&lt;p&gt;There are a few image CDNs that support using Client Hints.  I work at imgix, so naturally I have chosen to use imgix for this example.  imgix is an API based image management, optimization, &amp;amp; delivery service.  To use Client Hints with an image on imgix, you would simply add &lt;code&gt;ch=width, dpr&lt;/code&gt; to that image.  It also supports &lt;code&gt;save-data&lt;/code&gt;, but I'm not using that for this example.  &lt;/p&gt;

&lt;p&gt;In this example, I've added the &lt;code&gt;ch=width,dpr&lt;/code&gt; for client hints, then &lt;code&gt;w=400&lt;/code&gt; as the fallback size option for browsers that don't support it like Firefox or Safari. It's also important to add the &lt;code&gt;sizes&lt;/code&gt;; in my example below I'm not using any css so this determines what size my images should be.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;img src="https://imgix.tomdale.website/artsy/6.jpg?ch=width,dpr&amp;amp;w=400"
sizes="(min-width: 768px) 30vw, 100vw" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Let's look at a Demo
&lt;/h1&gt;

&lt;p&gt;I created a simple &lt;a href="https://ch-testing.vercel.app/"&gt;demo site&lt;/a&gt; to show this working.  It's important to note that I tried to make this site as simple as possible with minimal css to ensure any changes to the images were purely happening because of the Client Hints.  Please note that if you open a specific image in a separate tab by itself, it will not appear the same size as used on the website. It only sizes according to Client Hints when on the actual site.&lt;/p&gt;

&lt;p&gt;I've included 9 example images. Each image code is like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;img src="https://imgix.tomdale.website/artsy/5.jpg?ch=width,dpr&amp;amp;w=400&amp;amp;ar=4:3&amp;amp;fit=crop&amp;amp;crop=faces,edges&amp;amp;auto=format,compress" 
sizes="(min-width: 768px) 30vw, 100vw" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While in a supporting browser, like Chrome, the images will we 30% the width of the browser width when the browser is 768 pixels or larger. Once it goes smaller than that, each image will be sized at 100% the width of the browser. This is truly a dynamic size, every time you resize this browser and do a hard refresh you will notice the weight of the images change in the network tab.&lt;/p&gt;

&lt;p&gt;In an ideal world, you should also be using srcset in combination with Client Hints.  You do want to serve a good size image for the other 25% of users that aren't supported for Client Hints.  In this demo I did not do that because I wanted to focus on showing the size of these images.  You will also notice the cropping points of these images change a bit, that's because I am using some imgix API to automatically crop to a face first, then a prominent object in the photo as a fallback option if there are no faces.&lt;/p&gt;

&lt;h1&gt;
  
  
  Deploying to Vercel
&lt;/h1&gt;

&lt;p&gt;I enjoy using both Vercel &amp;amp; Netlify to deploy my sites.  They both have a lot of benefits.  In this example I did use Vercel.  The important item needed to make Client Hints work is setting a feature policy.  With Vercel, you can set that policy by adding a vercel.json file. For my demo I put this in the vercel.json file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "routes": [
    {
      "src": "/*",
        "headers": {
          "Accept-CH": "DPR, Width, Viewport-Width",
          "Feature-Policy": "ch-dpr https://imgix.tomdale.website 'self'; ch-width https://imgix.tomdale.website 'self'; ch-viewport-width https://imgix.tomdale.website 'self'"
        }
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should change that url to the url you are using for your images to make this work.  But, in order to serve Client Hints safely, this isn't that big of an effort to add.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;It's great to see Client Hints working again.  It's still not the 100% solution you can use, so you do still need to follow responsive image best practices with setting srcsets for different image breakpoints.  But Client Hints is certainly on the path to be the ideal solution in the future to serving those perfect responsive images.  Here is a link the &lt;a href="https://github.com/daletom/ch_testing"&gt;Github Repo&lt;/a&gt; for this project.  Feel free to reach out to me if you have any other questions as well!&lt;/p&gt;

</description>
      <category>imgix</category>
      <category>vercel</category>
      <category>clienthints</category>
      <category>responsive</category>
    </item>
  </channel>
</rss>
