<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Colby Fayock - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Colby Fayock - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 20 May 2026 20:47:09 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/colbyfayock/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Santa Tracker App with Next.js and React Leaflet ]]>
                </title>
                <description>
                    <![CDATA[ It's the holiday season and Santa's coming! But just like he watches all of us, we can build a map-based tracking app to keep an eye on him and find out when he'll come on Christmas night with Next.js and React Leaflet.        How ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-santa-tracker-app-with-next-js-react-leaflet/</link>
                <guid isPermaLink="false">66b8e347682e4a25eed2619e</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 21 Dec 2022 16:42:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/12/santa-tracking-map-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>It's the holiday season and Santa's coming! But just like he watches all of us, we can build a map-based tracking app to keep an eye on him and find out when he'll come on Christmas night with Next.js and React Leaflet.</p>
<ul>
  <li>
    <a href="#how-can-we-track-santa">How can we track Santa?</a>
  </li>
  <li>
    <a href="#how-can-i-create-a-map">How can I create a map?</a>
  </li>
  <li>
    <a href="#what-are-we-going-to-build">What are we going to build?</a>
  </li>
  <li>
    <a href="#step-0-creating-a-new-next-js-app-from-next-js-leaflet-starter">Step 0: Creating a new Next.js app from Next.js Leaflet Starter</a>
  </li>
  <li>
    <a href="#step-1-fetching-santa-data-with-swr">Step 1: Fetching Santa Data with SWR</a>
  </li>
  <li>
    <a href="#step-2-showing-santa-s-stops-on-a-map-with-react-leaflet-markers">Step 2: Showing Santa's Stops on a Map with React Leaflet Markers</a>
  </li>
  <li>
    <a href="#step-3-adjusting-santa-arrival-and-departure-datetimes-to-current-year">Step 3: Adjusting Santa arrival and departure datetimes to current year</a>
  </li>
  <li>
    <a href="#step-4-updating-markers-to-custom-icons">Step 4: Updating Markers to custom icons</a>
  </li>
  <li>
    <a href="#step-5-showing-where-santa-s-at-and-where-he-s-been-by-comparing-datetimes">Step 5: Showing where Santa's at and where he's been by comparing datetimes</a>
  </li>
</ul>

<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/kklt5gDs6Qw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-how-can-we-track-santa">How can we track Santa?</h2>
<p>The people who brought you <a target="_blank" href="https://github.com/google/santa-tracker-web">Google's Santa tracker</a> in years past created an <a target="_blank" href="https://firebasestorage.googleapis.com/v0/b/santa-tracker-firebase.appspot.com/o/route%2Fsanta_en.json?alt=media&amp;2018b">unofficial endpoint</a> that gives you a list of destinations where Santa stops for presents.</p>
<p>While there's a chance they might all of a sudden kill it, it's been running strong since 2019. So there's a good chance it will stay up (I also <a target="_blank" href="https://gist.github.com/colbyfayock/79bbaf5991dc776fb0db53fddb99db58">backed up the data to a Gist</a> 👀).</p>
<p>But with that data, we can add points on a map telling us the locations Santa will stop along with whether or not he's stopped there yet.</p>
<h2 id="heading-how-can-i-create-a-map">How can I create a map?</h2>
<p>We'll use <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a>, which is a wrapper around the popular <a target="_blank" href="https://leafletjs.com/">Leaflet</a> mapping library.</p>
<p>The library allows us to build a map and add lots of different types of visuals like data, imagery, or it can even create custom maps of sci-fi worlds if you get advanced enough.</p>
<p>But we'll use this to build our map to track Santa on.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We're going to build a Santa Tracker application that gives us a map with all of the destinations. It will tell use if Santa has stopped there, if Santa's currently there, and if he's already left.</p>
<p>We'll do this in Next.js by using a Starter I created called Next.js Leaflet Starter. This will give us our basic map that we can use to get productive in React Leaflet.</p>
<h2 id="heading-step-0-creating-a-new-nextjs-app-from-nextjs-leaflet-starter">Step 0: Creating a new Next.js app from Next.js Leaflet Starter</h2>
<p>We’re going to start off with a new Next.js app using the <a target="_blank" href="https://github.com/colbyfayock/next-leaflet-starter">Next.js Leaflet Starter</a>. This will get us moving quickly with a basic map we can start to play with.</p>
<p>Inside of your terminal, run:</p>
<pre><code class="lang-other">yarn create next-app -e https://github.com/colbyfayock/next-leaflet-starter my-santa-tracking-app
# or
npx create-next-app -e https://github.com/colbyfayock/next-leaflet-starter my-santa-tracking-app
</code></pre>
<p>Note: feel free to use a different value than <code>my-santa-tracking-app</code> as your project name!</p>
<p>Once installation has finished, you can navigate to that directory.</p>
<pre><code class="lang-other">cd my-santa-tracking-app
</code></pre>
<p>Then you can start your local development server with:</p>
<pre><code class="lang-other">yarn dev
# or
npm run dev
</code></pre>
<p>And once you visit it in your browser at <a target="_blank" href="http://localhost:3000">http://localhost:3000</a>, we should see our new application:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/nextjs-leaflet-starter.jpg" alt="New application with map from Next.js Leaflet Starter" width="600" height="400" loading="lazy">
<em>Next.js Leaflet Starter</em></p>
<p>If we take a second to browse around the project, we're primarily interested in the homepage managed inside <code>src/pages/index.js</code> for this tutorial. There, along with some basic UI, we have a map.</p>
<p>The map is built by wrapping the React Leaflet Map with a <a target="_blank" href="https://nextjs.org/docs/advanced-features/dynamic-import">Next.js Dynamic Import</a>. The tricky thing with Leaflet and React Leaflet is that it requires the browser's window object to work. So we use the Dynamic Import to only load it once it hits the client.</p>
<p>But in the homepage, we can see how we're currently utilizing our map, along with some introductory components, which will allow us to get started building our tracker app!</p>
<h2 id="heading-step-1-fetching-santa-data-with-swr">Step 1: Fetching Santa Data with SWR</h2>
<p>In order to get our Santa data, we need to fetch it from our API.</p>
<p>While we could technically just use fetch and store it in state, let's use <a target="_blank" href="https://swr.vercel.app/">SWR</a> which gives us a little bit cleaner of a way to manage that request.</p>
<p>In your terminal, first install SWR with:</p>
<pre><code class="lang-other">yarn add swr
# or
npm install swr
</code></pre>
<p>Next, let's import it into our project.</p>
<p>At the top of <code>src/pages/index.js</code> add:</p>
<pre><code class="lang-other">import useSWR from 'swr';
</code></pre>
<p>And to use our newly imported SWR hook, we have two parts, where first let's define our "fetch" function, which is essentially the abstracted request logic.</p>
<p>Above the Home page component add:</p>
<pre><code class="lang-other">const fetcher = (url) =&gt; fetch(url).then((res) =&gt; res.json());
</code></pre>
<p>And then we can set up the request itself inside, at the top of our Home page component:</p>
<pre><code class="lang-other">const { data } = useSWR(
  'https://firebasestorage.googleapis.com/v0/b/santa-tracker-firebase.appspot.com/o/route%2Fsanta_en.json?alt=media&amp;2018b',
  fetcher
);
</code></pre>
<p>To quickly review what's happening, we're using the useSWR hook which will give us some data fetching features (caching, revalidation). But we need to tell SWR 2 things: how to fetch the data (fetcher) and where (our endpoint).</p>
<p>And with that, we should have our data, which we can now test by adding a console log. There, when we load our page and look in the console, we should see a bunch of destinations logged out:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/santa-destination-data.jpg" alt="Browser showing page with map and developer console with Santa destination data" width="600" height="400" loading="lazy">
<em>Santa destinations</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracking-app/commit/e9afb6f224744195c6a1118a0aab639770da26b6">Follow along with the commit!</a></p>
<h2 id="heading-step-2-showing-santas-stops-on-a-map-with-react-leaflet-markers">Step 2: Showing Santa's Stops on a Map with React Leaflet Markers</h2>
<p>We have Santa's future stops! Now let's throw them on the map.</p>
<p>If we scroll down to our Map component, we should see that we're nesting two components:</p>
<ul>
<li>Tilelayer: this is the background, the actual map imagery</li>
<li>Marker: the pin that's dropped on the map (and a Popup inside)</li>
</ul>
<p>These are abstracted as React components, so like any other React component, we can map through our data adding a new Marker for every stop.</p>
<p>Let's replace the Marker component with:</p>
<pre><code class="lang-other">{data?.destinations?.map(({ id, location, city, region }) =&gt; {
  return (
    &lt;Marker key={id} position={[location.lat, location.lng]}&gt;
      &lt;Popup&gt;{ city }, { region }&lt;/Popup&gt;
    &lt;/Marker&gt;
  )
})}
</code></pre>
<p>If we reload the page, we'll see...the same thing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/map-marker-washington-dc.jpg" alt="Map showing pin on Washington, DC" width="600" height="400" loading="lazy">
<em>Still showing Washington, DC</em></p>
<p>But this is deceiving. Zoom out on the map and we'll see all of our pins:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/map-markers-santa-locations-united-states.jpg" alt="Map showing pins on northeast United States" width="600" height="400" loading="lazy">
<em>Zoomed out showing pins</em></p>
<p>We can even click each of those pins, which we'll see the location of since we added it in a Popup.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/map-marker-popup-buenos-aires-argentina.jpg" alt="Map showing open popup over Buenos Aires, Argentina" width="600" height="400" loading="lazy">
<em>World Cup 2022 winner with location popup!</em></p>
<p>Everything is working well so far, but we don't want people to have to zoom out every time, so let's fix that.</p>
<p>On the Map component, we can see a <code>center</code> prop and a <code>zoom</code> prop:</p>
<ul>
<li>Center: the default location to center the map on</li>
<li>Zoom: the zoom left the map starts with</li>
</ul>
<p>Let's make those more appropriate for our project:</p>
<pre><code class="lang-other">&lt;Map ... center={[0, 0]} zoom={1}&gt;
</code></pre>
<p>This will set it in the center of the world with a zoom level of 1, which lets us see the entire world.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/world-map-markers-santa-locations.jpg" alt="Map with pins on cities all over the world" width="600" height="400" loading="lazy">
<em>Map showing pins all over world</em></p>
<p>Now as one final thing, instead of only showing what the location name is, let's add when Santa will arrive.</p>
<p>Update the map statement for destinations with:</p>
<pre><code class="lang-other">{data?.destinations?.map(({ id, arrival, departure, location, city, region }) =&gt; {
  const arrivalDate = new Date(arrival);
  const arrivalHours = arrivalDate.getHours()
  const arrivalMinutes = arrivalDate.getMinutes()
  const arrivalTime = `${arrivalHours}:${arrivalMinutes}`;

  const departureDate = new Date(departure);
  const departureHours = departureDate.getHours()
  const departureMinutes = departureDate.getMinutes()
  const departureTime = `${departureHours}:${departureMinutes}`;

  return (
    &lt;Marker key={id} position={[location.lat, location.lng]}&gt;
      &lt;Popup&gt;
        &lt;strong&gt;Location:&lt;/strong&gt; { city }, { region }
        &lt;br /&gt;
        &lt;strong&gt;Arrival:&lt;/strong&gt; { arrivalDate.toDateString() } @ { arrivalTime }
        &lt;br /&gt;
        &lt;strong&gt;Departure:&lt;/strong&gt; { arrivalDate.toDateString() } @ { departureTime }
      &lt;/Popup&gt;
    &lt;/Marker&gt;
  )
})}
</code></pre>
<p>Here we're:</p>
<ul>
<li>Using the arrival and departure times to create new dates</li>
<li>Getting specific values for both date and time</li>
<li>Formatting the time</li>
<li>Adding arrival and departure datetimes to Popup</li>
</ul>
<p>And when we reload the page and click on a pin, we should see all of our information!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/map-marker-arrival-depature-ukraine-santa.jpg" alt="Map showing open popup over Ukraine pin" width="600" height="400" loading="lazy">
<em>Ukraine's Santa destination</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracking-app/commit/5ef0edea4c8ff3fe01fd40326c5c001dcc06411d">Follow along with the commit!</a></p>
<h2 id="heading-step-3-adjusting-santa-arrival-and-departure-datetimes-to-current-year">Step 3: Adjusting Santa arrival and departure datetimes to current year</h2>
<p>Plot twist! The API we're using to load Santa's destinations is currently showing 2019 😱.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/map-marker-highlighted-old-date-3.jpg" alt="Map highlighting 2019 date in Popup" width="600" height="400" loading="lazy">
<em>Santa's in the past!</em></p>
<p>Turns out that after 2019, Google stopped updating this API. But that's okay, the timings and locations remain the same, we just need to correct it to the current year, which we can do dynamically to also future proof this.</p>
<p>At the top of the Home page component and under the SWR request, let's first get the current date and time:</p>
<pre><code class="lang-other">const currentDate = new Date(Date.now());
const currentYear = currentDate.getFullYear();
</code></pre>
<p>Next, we can create a new "corrected" set of destinations:</p>
<pre><code class="lang-other">const destinations = data?.destinations.map((destination) =&gt; {
  const { arrival, departure } = destination;

  const arrivalDate = new Date(arrival);
  const departureDate = new Date(departure);

  arrivalDate.setFullYear(currentYear);
  departureDate.setFullYear(currentYear);

  return {
    ...destination,
    arrival: arrivalDate.getTime(),
    departure:  departureDate.getTime(),
  }
});
</code></pre>
<p>Here we're:</p>
<ul>
<li>Mapping through each destination, ultimately creating a new array of <code>destinations</code></li>
<li>Getting the arrival and departure dates into a new Date object</li>
<li>Using our <code>currentYear</code> value to adjust our arrival and departure</li>
<li>Returning all the destination data with the updated values</li>
</ul>
<p>Finally as one last step, we need to update the code that's creating our Markers from <code>data?.destinations?.map</code> to:</p>
<pre><code class="lang-other">{destinations?.map(({ id, arrival, departure, location, city, region }) =&gt; {
</code></pre>
<p>And if we open up our app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/map-marker-popup-2022.jpg" alt="Map showing popup open with current year" width="600" height="400" loading="lazy">
<em>Popups with correct date!</em></p>
<p>We should now see that all of our popups have the right date.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracking-app/commit/e4126ad9e428b18f50d2509c539236bbdfaa8133">Follow along with the commit!</a></p>
<h2 id="heading-step-4-updating-markers-to-custom-icons">Step 4: Updating Markers to custom icons</h2>
<p>Right now we're using the default graphics that come with React Leaflet for our Markers, but we can do better.</p>
<p>We can provide our own custom images that will replace the marker, including something fun like Christmas trees!</p>
<p>To help out, I created an image for this already, which you can grab here:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/tree-marker-icon-2x.png" alt="Christmas Tree Icon @2x" width="600" height="400" loading="lazy">
<em>2x: <a target="_blank" href="https://github.com/colbyfayock/my-santa-tracking-app/blob/main/public/images/tree-marker-icon-2x.png">https://github.com/colbyfayock/my-santa-tracking-app/blob/main/public/images/tree-marker-icon-2x.png</a></em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/tree-marker-icon.png" alt="Christmas Tree Icon @1x" width="600" height="400" loading="lazy">
<em>1x: <a target="_blank" href="https://github.com/colbyfayock/my-santa-tracking-app/blob/main/public/images/tree-marker-icon.png">https://github.com/colbyfayock/my-santa-tracking-app/blob/main/public/images/tree-marker-icon.png</a></em></p>
<p>Note: you can use whatever images you want, you'll just need to be sure to adjust the sizes and use the right filenames.</p>
<p>First, place your images inside of the <code>public/images</code> directory to make them available for us to use.</p>
<p>Then we're going to tell our Marker we want to use our custom icon.</p>
<p>To start, we need to make the Leaflet library available to use in our Map component:</p>
<pre><code class="lang-other">&lt;Map className={styles.homeMap} width="800" height="400" center={[0, 0]} zoom={1}&gt;
  {({ TileLayer, Marker, Popup }, Leaflet) =&gt; (
</code></pre>
<p>Here we're adding the <code>Leaflet</code> variable as a second argument to our function prop.</p>
<p>Then we need to use it to create our icon using a Leaflet Icon instance.</p>
<p>Inside of our <code>destinations</code> map, update the Marker opening tag to:</p>
<pre><code class="lang-other">&lt;Marker
  key={id}
  position={[location.lat, location.lng]}
  icon={Leaflet.icon({
    iconUrl: '/images/tree-marker-icon.png',
    iconRetinaUrl: '/images/tree-marker-icon-2x.png',
    iconSize: [41, 41]
  })}
&gt;
</code></pre>
<p>Here we're adding a new prop of <code>icon</code> to our Marker where we're creating a new Leaflet Icon along with the path to our Icons.</p>
<p>We additionally specify the size as we're providing square images as opposed to the rectangular images that are there by default.</p>
<p>And just like that, we now have Christmas tree markers!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/map-santa-locations-christmas-trees.jpg" alt="Map showing Santa locations with Christmas tree markers" width="600" height="400" loading="lazy">
<em>Christmas tree marker icons!</em></p>
<p>But we can take this a step further and show where Santa is with a custom icon as well as where he's already been with another custom icon, which we'll do in the next step.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracking-app/commit/8e44f8c9bae9e83a0e99d5c4e27575017f7d947a">Follow along with the commit!</a></p>
<h2 id="heading-step-5-showing-where-santas-at-and-where-hes-been-by-comparing-datetimes">Step 5: Showing where Santa's at and where he's been by comparing datetimes</h2>
<p>Previously, we set up our custom icons for all of Santa's stops.</p>
<p>We can take that further and use Santa's arrival and departure times to determine if he's currently at a location and if he was at a location, then show different icons.</p>
<p>This will include a couple of steps:</p>
<ul>
<li>Determining if Santa "is here" and "was here"</li>
<li>Adding and showing different icons</li>
<li>Faking the current time to test that it works</li>
</ul>
<p>Starting off, let's figure out where Santa currently is.</p>
<p>For every destination, we have our arrival time and departure time, which we're already using in the Popup. We can compare those values to the current time to determine where he is.</p>
<p>Inside of the destinations map and right before the return statement (under the time variables) add:</p>
<pre><code class="lang-other">const santaWasHere = currentDate.getTime() - departureDate.getTime() &gt; 0;
const santaIsHere = currentDate.getTime() - arrivalDate.getTime() &gt; 0 &amp;&amp; !santaWasHere;
</code></pre>
<p>Here we're determining:</p>
<ul>
<li>If Santa <strong>was</strong> here – essentially if the current time is later than the departure time</li>
<li>If Santa <strong>is</strong> here – essentially if the current time is later than the arrival time AND Santa hasn't left (the above is false)</li>
</ul>
<p>Next, we need to dynamically set our icon URLs to use new icons in different time instances.</p>
<p>To do that, we need new images. Luckily, I'm providing them for you again!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/gift-marker-icon-2x.png" alt="Gift Icon @2x" width="600" height="400" loading="lazy">
<em>Gift 2x: https://github.com/colbyfayock/my-santa-tracking-app/blob/main/public/images/gift-marker-icon-2x.png</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/gift-marker-icon.png" alt="Gift Icon @1x" width="600" height="400" loading="lazy">
<em>Gift 1x: https://github.com/colbyfayock/my-santa-tracking-app/blob/main/public/images/gift-marker-icon.png</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/santa-marker-icon-2x.png" alt="Santa Icon @2x" width="600" height="400" loading="lazy">
<em>Santa 2x: https://github.com/colbyfayock/my-santa-tracking-app/blob/main/public/images/santa-marker-icon-2x.png</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/santa-marker-icon.png" alt="Santa Icon @1x" width="600" height="400" loading="lazy">
<em>Santa 1x: https://github.com/colbyfayock/my-santa-tracking-app/blob/main/public/images/santa-marker-icon.png</em></p>
<p>Like before, we want to drop all four images into the <code>public/images</code> directory.</p>
<p>Note: again, you can use different images if you'd like, but be sure to pay attention to the size and filenames.</p>
<p>With our images, we can set up our dynamic image URL.</p>
<p>First, let's create a variable to store this information:</p>
<pre><code class="lang-other">let iconUrl = '/images/tree-marker-icon.png';
let iconRetinaUrl = '/images/tree-marker-icon-2x.png';
</code></pre>
<p>And update our Marker <code>icon</code> prop to use these variables:</p>
<pre><code class="lang-other">&lt;Marker
  key={id}
  position={[location.lat, location.lng]}
  icon={Leaflet.icon({
    iconUrl,
    iconRetinaUrl,
    iconSize: [41, 41]
  })}
&gt;
</code></pre>
<p>Putting it all together, we can check our time comparisons and set the URL based on that:</p>
<pre><code class="lang-other">if ( santaIsHere ) {
  iconUrl = '/images/santa-marker-icon.png';
  iconRetinaUrl = '/images/santa-marker-icon-2x.png';
}

if ( santaWasHere ) {
  iconUrl = '/images/gift-marker-icon.png';
  iconRetinaUrl = '/images/gift-marker-icon-2x.png';
}
</code></pre>
<p>If we open the map, we'll notice we have an issue. It's not Christmas yet, so how do we know if this is going to work?</p>
<p>We can fake the time to check!</p>
<p>At the top of the Home component, let's comment out our <code>currentDate</code> and set it to a static value:</p>
<pre><code class="lang-other">// const currentDate = new Date(Date.now());
const currentDate = new Date('2022-12-25T02:34:30.115Z');
</code></pre>
<p>If we look at our map:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/map-gifts-trees-santa-locations.jpg" alt="Map showing gifts where Santa has already been" width="600" height="400" loading="lazy">
<em>So many gifts!</em></p>
<p>We should now see that because we set the time to Dec 25 at 2:34:30 UTC, which is Dec 24th around 9:34pm EST, we should see that Santa has started to give gifts in most of the world, but not quite yet on the east coast of the United States.</p>
<p>Now a tiny little issue, did you find Santa yet?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/santa-hiding-behind-tree.jpg" alt="Santa covered by a tree icon on the map" width="600" height="400" loading="lazy">
<em>Santa!</em></p>
<p>There he is! Peeking around a tree from Buenos Aires.</p>
<p>This isn't ideal, as Santa is arguably the most important icon, right?</p>
<p>So we can fix this with a little CSS.</p>
<p>Similar to our icon URL, we're going to create a new variable to add a class dynamically to our icon.</p>
<p>First, the className variable:</p>
<pre><code class="lang-other">let className = '';

if ( santaIsHere ) {
  className = `${className} ${styles.iconSantaIsHere}`;
}
</code></pre>
<p>And then we apply that to our icon prop:</p>
<pre><code class="lang-other">&lt;Marker
  key={id}
  position={[location.lat, location.lng]}
  icon={Leaflet.icon({
    iconUrl,
    iconRetinaUrl,
    iconSize: [41, 41],
    className
  })}
&gt;
</code></pre>
<p>Then we can open up <code>src/styles/Home.scss</code> and add the following at the bottom:</p>
<pre><code class="lang-other">.iconSantaIsHere {
  z-index: 9999!important;
}
</code></pre>
<p>And once we reload the page, we should now see Santa at the top of all of the icons:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/12/santa-map-marker-zindex-fix.jpg" alt="Santa icon above all other icons on map" width="600" height="400" loading="lazy">
<em>Santa clear on the map</em></p>
<p>Before moving on...</p>
<p><strong>Important:</strong> be sure to update your <code>currentDate</code> variable to:</p>
<pre><code class="lang-other">const currentDate = new Date(Date.now());
</code></pre>
<p>We don't want to be disappointed when the tracker isn't... tracking.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracking-app/commit/09884333eb965b3130a22affe29e50bcaf8e6d35">Follow along with the commit!</a></p>
<h2 id="heading-what-else-can-we-do">What else can we do?</h2>
<p>Hope you had fun and that this put you in the holiday spirit! Looking to take it to another level? Here are a few more things you can do.</p>
<h3 id="heading-refresh-the-time-to-update-santas-location">Refresh the time to update Santa's location</h3>
<p>When you first load the page, we get a <code>currentDate</code> value, but that won't update throughout the night.</p>
<p>If you want to keep this app up and actively see where Santa is traveling to, try moving the time to React state and set an interval that automatically updates it every so often, such as every 30 seconds.</p>
<h3 id="heading-show-santas-location-if-hes-not-at-a-stop">Show Santa's location if he's not at a stop</h3>
<p>The static time I used to test where Santa was at was 2:34:30, which wasn't a coincidence. If I had set it to 2:34:00, he wouldn't have been at a location, rather, he would have been traveling to one.</p>
<p>Using this information, we can determine where Santa is by:</p>
<ul>
<li>Finding the last destination Santa departed</li>
<li>Finding the next destination where Santa will arrive</li>
<li>Finding the middle of the two geographical locations (latitude and longitude)</li>
<li>Adding a Marker to that location</li>
</ul>
<p>One way is by using JS library Turf, which along with a lot of other tools, allows you to find the midpoint between two locations:</p>
<p><a target="_blank" href="https://turfjs.org/docs/#midpoint">https://turfjs.org/docs/#midpoint</a></p>
<h3 id="heading-customize-and-style-the-map">Customize and style the map</h3>
<p>It's Christmas! We don't want a boring map and application.</p>
<p>We can use tools like Mapbox to change the map imagery and CSS to theme our app.</p>
<p>This tutorial is for using Mapbox with Gatsby but the concepts should generally be the same: <a target="_blank" href="https://www.youtube.com/watch?v=KcPJr1b_rv0">https://www.youtube.com/watch?v=KcPJr1b_rv0</a>.</p>
<h3 id="heading-add-santas-path-so-you-know-where-hes-going-next">Add Santa's path so you know where he's going next</h3>
<p>We see a bunch of locations, but we don't know where Santa is going when.</p>
<p>React Leaflet allows us to add other "shapes" to the map, such as a <a target="_blank" href="https://react-leaflet.js.org/docs/api-components/#polyline">Polyline</a>, where we can pass in an array of points.</p>
<p>The only issue is after you try that, because our line crosses over the Antimeridian, we get big zig-zags on our map.</p>
<p>This one will be a challenge, but try using the library Leaflet Antimeridian to fix this issue:</p>
<p><a target="_blank" href="https://github.com/briannaAndCo/Leaflet.Antimeridian">https://github.com/briannaAndCo/Leaflet.Antimeridian</a></p>
<p>Tip: I <a target="_blank" href="https://github.com/colbyfayock/santa-tracker/blob/1b231ed40c43abdeeeeaa57fa16a0fea684d8085/src/lib/santa.js#L70">implemented this in Gatsby a few years ago</a>. Maybe try checking out what I did there, again, the concepts should be the same.</p>
<h2 id="heading-share-your-tracker-with-me">Share your tracker with me!</h2>
<p>Send a Tweet with a link to your deployed Santa Tracker and tag me <a target="_blank" href="https://twitter.com/colbyfayock">@colbyfayock</a>.</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">🐦 Follow On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">📺 Subscribe on Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">📫 Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>

 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Sass with CSS Modules in Next.js ]]>
                </title>
                <description>
                    <![CDATA[ Next.js gives us CSS Modules by default, providing benefits like scoped styles and focused development in our app. How can we give our Next.js CSS superpowers with Sass? What are CSS Modules? What is Sass? What are we going to build? Step 0: Creatin... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-sass-with-css-modules-in-next-js/</link>
                <guid isPermaLink="false">66b8e3790a89d796f29a16f7</guid>
                
                    <category>
                        <![CDATA[ CSS Modules ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Sass ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 07 Jan 2021 17:31:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/01/Article.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Next.js gives us CSS Modules by default, providing benefits like scoped styles and focused development in our app. How can we give our Next.js CSS superpowers with Sass?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-css-modules">What are CSS Modules?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-sass">What is Sass?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-step-0-creating-a-new-nextjs-app">Step 0: Creating a new Next.js app</a></li>
<li><a class="post-section-overview" href="#heading-step-1-installing-sass-in-a-nextjs-app">Step 1: Installing Sass in a Next.js app</a></li>
<li><a class="post-section-overview" href="#heading-step-2-importing-sass-files-into-a-nextjs-app">Step 2: Importing Sass files into a Next.js app</a></li>
<li><a class="post-section-overview" href="#heading-step-3-using-sass-variables-in-a-nextjs-app">Step 3: Using Sass variables in a Next.js app</a></li>
<li><a class="post-section-overview" href="#heading-step-4-using-sass-mixins-with-global-imports-in-nextjs">Step 4: Using Sass mixins with global imports in Next.js</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/C1-hmauMht0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-are-css-modules">What are CSS Modules?</h2>
<p><a target="_blank" href="https://github.com/css-modules/css-modules">CSS Modules</a> are essentially CSS files that, when imported into JavaScript projects, provide styles that are scoped to that particular part of the project by default.</p>
<p>When importing your module, the classes are represented by an object mapped with each class name, allowing you to apply that class right to your project.</p>
<p>For instance, if I had a CSS module for the title of my page:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.title</span> {
  <span class="hljs-attribute">color</span>: blueviolet;
}
</code></pre>
<p>And I import that into my React project:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'./my-styles.css'</span>
</code></pre>
<p>I can then apply that title right to an element as if it were a string:</p>
<pre><code class="lang-jsx">&lt;h1 className={styles.title}&gt;My Title&lt;/h1&gt;
</code></pre>
<p>By scoping styles, you no longer have to worry about breaking other parts of the application with cascading styles. It’s also easier to manage smaller chunks of code that pertain to a specific piece of the application.</p>
<h2 id="heading-what-is-sass">What is Sass?</h2>
<p><a target="_blank" href="https://sass-lang.com/">Sass</a> is an extension of the CSS language that provides powerful features like variables, functions, and other operations that allow you to more easily build complex features into your project.</p>
<p>As an example, if I wanted to store my color above in a variable so I can easily change it later, I can add:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$color-primary</span>: blueviolet;

<span class="hljs-selector-class">.title</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-variable">$color-primary</span>;
}
</code></pre>
<p>If I wanted to change that color but only in one spot, I can use built-in color functions to change the shade:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$color-primary</span>: blueviolet;

<span class="hljs-selector-class">.title</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-variable">$color-primary</span>;
  <span class="hljs-attribute">border-bottom</span>: solid <span class="hljs-number">2px</span> darken(<span class="hljs-variable">$color-primary</span>, <span class="hljs-number">10</span>);
}
</code></pre>
<p>One additional benefit is the ability to nest styles. This allows for easier, more logical organization of your CSS.</p>
<p>For instance, if I wanted to change only a <code>&lt;strong&gt;</code> element nested in a title, I can add:</p>
<pre><code>$color-primary: blueviolet;
$color-secondary: cyan;

.title {

  <span class="hljs-attr">color</span>: $color-primary;
  border-bottom: solid <span class="hljs-number">2</span>px darken($color-primary, <span class="hljs-number">10</span>);

  strong {
    <span class="hljs-attr">color</span>: $color-secondary;
  }

}
</code></pre><h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We're going to create a new <a target="_blank" href="https://reactjs.org/">React</a> app using <a target="_blank" href="https://nextjs.org/">Next.js</a>.</p>
<p>With our new app, we'll learn how to install and configure Sass so that we can take advantage its features inside of Next.js.</p>
<p>Once set up Sass, we'll walk through how to use Sass <a target="_blank" href="https://sass-lang.com/documentation/variables">variables</a> and <a target="_blank" href="https://sass-lang.com/documentation/at-rules/mixin">mixins</a> to recreate some of the default elements of the Next.js UI.</p>
<blockquote>
<p>Want to skip the tutorial and dive into the code? Check out <a target="_blank" href="https://github.com/colbyfayock/next-sass-starter">Next.js Sass Starter on GitHub</a>: <a target="_blank" href="https://github.com/colbyfayock/next-sass-starter"><em>https://github.com/colbyfayock/next-sass-starter</em></a></p>
</blockquote>
<h2 id="heading-step-0-creating-a-new-nextjs-app">Step 0: Creating a new Next.js app</h2>
<p>To get started with a new Next.js app, we can use <a target="_blank" href="https://nextjs.org/docs/api-reference/create-next-app">Create Next App</a>.</p>
<p>In your terminal, navigate to where you want to create the new project and run:</p>
<pre><code>yarn create next-app my-next-sass-app
</code></pre><p><em>Note: you can use npm instead of yarn for any examples with installation and package management.</em></p>
<p>Once the installation finishes, you can navigate into the directory, and start your development server:</p>
<pre><code>yarn dev
</code></pre><p>Which should start your new Next.js project at <a target="_blank" href="http://localhost:3000">http://localhost:3000</a>!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/nextjs-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js app</em></p>
<p>If this is your first time creating a new Next.js app, have a look around! It comes with a basic homepage as well as two CSS files:</p>
<ul>
<li><code>/styles/globals.css</code></li>
<li><code>/styles/Home.module.css</code></li>
</ul>
<p>Here we’ll be focusing on the home file. If you look inside <code>pages/index.js,</code> there, you’ll see that we’re importing the home file, making those styles available.</p>
<p>Next.js has CSS Modules built in by default. This means that when we import our home styles file, the CSS classes are added to the styles object, and we apply each of those class names to the React elements from that object, such as:</p>
<pre><code class="lang-jsx">&lt;h1 className={styles.title}&gt;
</code></pre>
<p>That means that our styles are scoped to that single page.</p>
<p>To learn more about CSS Modules or the built-in support in Next.js, you can check out the following resources:</p>
<ul>
<li><a target="_blank" href="https://github.com/css-modules/css-modules">https://github.com/css-modules/css-modules</a></li>
<li><a target="_blank" href="https://nextjs.org/docs/basic-features/built-in-css-support">https://nextjs.org/docs/basic-features/built-in-css-support</a></li>
</ul>
<h2 id="heading-step-1-installing-sass-in-a-nextjs-app">Step 1: Installing Sass in a Next.js app</h2>
<p>While Next.js comes with some good built-in CSS support, it doesn’t come with Sass completely built in.</p>
<p>Luckily, to get Sass up and running inside of our Next.js app, all we need to do is install the <a target="_blank" href="https://www.npmjs.com/package/sass">Sass package</a> from npm, which will let Next.js include those files in its pipeline.</p>
<p>To install Sass, run the following inside of your project:</p>
<pre><code>yarn add sass
</code></pre><p>And if we start back up our development server and reload the page, we’ll actually notice that nothing has happened yet, which is a good thing!</p>
<p>But next we’ll learn how to take advantage of our CSS superpowers.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-next-sass-app/commit/053b07ccaa1eb30a7d0eff15e2e24470564092f6">Follow along with the commit!</a></p>
<h2 id="heading-step-2-importing-sass-files-into-a-nextjs-app">Step 2: Importing Sass files into a Next.js app</h2>
<p>Now that Sass is installed, we’re ready to use it.</p>
<p>In order you use any Sass-specific features though, we’ll need to use Sass files with either the <code>.sass</code> or <code>.scss</code> extension. For this walkthrough, we’re going to use the SCSS syntax and the <code>.scss</code> extension.</p>
<p>To get started, inside of <code>pages/index.js</code>, change the import of the styles object at the top of the page to:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'../styles/Home.module.scss'</span>
</code></pre>
<p>And once the page reloads, as we probably expect, the page is actually broken.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/nextjs-error-import.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js failed to compile</em></p>
<p>To fix this, rename the file:</p>
<pre><code>/styles/Home.module.css
</code></pre><p>to</p>
<pre><code>/styles/Home.module.scss
</code></pre><p>The difference is we’re changing the file extension from <code>.css</code> to <code>.scss</code>.</p>
<p>Once the page reloads, we’ll see that our Next.js site is loading and is back ready for action!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/nextjs-app-title.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New.js app loading</em></p>
<p>_Note: We’re not going to cover the global styles file here – you can do the same thing by renaming the global styles file and updating the import inside of <code>/pages/_app.js</code>_</p>
<p>Next, we’ll learn how to use Sass features for our Next.js app.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-next-sass-app/commit/cf2a3f56688a728163f2e2d3229565c4efdd6661">Follow along with the commit!</a></p>
<h2 id="heading-step-3-using-sass-variables-in-a-nextjs-app">Step 3: Using Sass variables in a Next.js app</h2>
<p>Now that we’re using Sass in our project, we can start using some of the basic features like variables.</p>
<p>To show how this works, we’re going to update the blue inside of our app to my favorite color, purple!</p>
<p>At the top of <code>/styles/Home.module.css</code>, add the following:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$color-primary</span>: <span class="hljs-number">#0070f3</span>;
</code></pre>
<p>The color <code>#0070f3</code> is what Next.js uses by default in the app.</p>
<p>Next, update each location that uses that color in our home CSS file to our new variables, such as changing:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.title</span> <span class="hljs-selector-tag">a</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#0070f3</span>;
</code></pre>
<p>to</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.title</span> <span class="hljs-selector-tag">a</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-variable">$color-primary</span>;
</code></pre>
<p>If we refresh the page, nothing should change.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/nextjs-app-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Unchanged Next.js app</em></p>
<p>But now because we’re using a variable to define that color, we can easily change it.</p>
<p>At the top of the page, change the <code>$color-primary</code> variable to purple or whatever your favorite color is:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$color-primary</span>: blueviolet;
</code></pre>
<p>And when the page reloads, we can see that our colors are now purple!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/nextjs-app-purple.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app with purple color</em></p>
<p>Variables are just the start to the superpowers Sass gives our CSS, but we can see that they allow us to easily manage our colors or other values throughout our application.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-next-sass-app/commit/0a9e72485957154cfc6a9dbe68f2d9d0d056daed">Follow along with the commit!</a></p>
<h2 id="heading-step-4-using-sass-mixins-with-global-imports-in-nextjs">Step 4: Using Sass mixins with global imports in Next.js</h2>
<p>One of the other many features of Sass is mixins. They give us the ability to create function-like definitions, allowing us to configure rules that we can repeat and use throughout our app.</p>
<p>In our example, we’re going to create a new mixin that allows us to create responsive styles using a media query throughout our app. While we can already do that with a media query alone, using a mixin allows us to use a single definition, keeping that consistent and allowing us to manage that responsive definition from one place.</p>
<p>Because this mixin is something we want to use throughout our entire application, we can also use another feature of Sass, which is the ability to import files.</p>
<p>To get started, create a new file under the <code>/styles</code> directory:</p>
<pre><code>/styles/_mixins.scss
</code></pre><p>We’re using an underscore in front of our filename to denote that it’s a partial.</p>
<p>Next, inside of our <code>/styles/Home.module.scss</code> file, let’s import that new file:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@import</span> <span class="hljs-string">"mixins"</span>;
</code></pre>
<p>Once the page reloads, we’ll notice nothing changed.</p>
<p>If we lookout the bottom of <code>Home.module.scss</code>, we’ll see that we’re using a media query to make the <code>.grid</code> class responsive. We’re going to use that as a basis for our mixin.</p>
<p>Inside of <code>_mixins.scss</code>, add the following:</p>
<pre><code>@mixin desktop() {
  @media (max-width: <span class="hljs-number">600</span>px) {
    @content;
  }
}
</code></pre><p><em>Note: while we probably can come up with a better name for this mixin than desktop, we’ll use that as the basis of our example.</em></p>
<p>The <code>@content</code> means that any time we use our desktop mixin, it will include the nested content in that location.</p>
<p>To test this out, back in our <code>Home.module.css</code> file, let’s update our <code>.grid</code> snippet:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@include</span> desktop() {
  <span class="hljs-selector-class">.grid</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">flex-direction</span>: column;
  }
}
</code></pre>
<p>If we open our app back up and shrink the browser window, we can see that we still have our responsive styles!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/nextjs-responsive-styles.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Responsive styles in Next.js</em></p>
<p>We can even take this a step further. Sass allows you to nest styles. For instance, instead of writing:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.footer</span> {
  // Styles
}

<span class="hljs-selector-class">.footer</span> <span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0.5rem</span>;
}
</code></pre>
<p>We can include that <code>img</code> definition right inside of the original <code>.footer</code> definition:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.footer</span> {

  <span class="hljs-comment">// Styles</span>

  <span class="hljs-selector-tag">img</span> {
    <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0.5rem</span>;
  }

}
</code></pre>
<p>That img definition will compile to <code>.footer img</code>, just the same as if it was written in standard CSS.</p>
<p>So with that in mind, we can use the same concept and move our desktop mixin into our original <code>.grid</code> class:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.grid</span> {

  <span class="hljs-keyword">@include</span> desktop() {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">flex-direction</span>: column;
  }

}
</code></pre>
<p>And if you notice, because we’re inside of the <code>.grid</code> class already, we can remove that from inside of the mixin, as it will already be applied.</p>
<p>This allows for much easier organization of our responsive styles.</p>
<p>Finally, if we look back at our app, we’ll notice that still, nothing has changed, which means we’re successfully using our Sass mixin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/nextjs-responsive-styles-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>No change in our Next.js app</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-next-sass-app/commit/6781916d8c12225c85dfde96bdab59bfaa14e22b">Follow along with the commit!</a>  </p>
<h2 id="heading-what-else-can-we-do-with-sass-and-nextjs">What else can we do with Sass and Next.js?</h2>
<p>We’re only scratching the surface here with Sass. Because our CSS modules now have the power of Sass, we have a ton of capabilities that don’t come by default with CSS.</p>
<h3 id="heading-color-functions">Color Functions</h3>
<p>Sass has a ton of functions built in that allow us to manipulate colors, mixing and matching shades much more easily.</p>
<p>Two that I use often are <a target="_blank" href="https://sass-lang.com/documentation/modules/color#darken">darken</a> and <a target="_blank" href="https://sass-lang.com/documentation/modules/color#lighten">lighten</a>, that allow you to take a color and change the shade.</p>
<p><a target="_blank" href="https://sass-lang.com/documentation/modules/color">Learn more about all of the available color functions in Sass.</a></p>
<h3 id="heading-custom-functions">Custom Functions</h3>
<p>While mixins seem like functions, we can define true functions in Sass that allow us to perform complex operations and produce values based on an input.</p>
<p><a target="_blank" href="https://sass-lang.com/documentation/values/functions">Learn more about custom functions in Sass.</a></p>
<h3 id="heading-other-value-types">Other Value Types</h3>
<p>While most of the time with CSS we’re using strings or numbers, we saw that a simple extension of that is the ability to use variables.</p>
<p>In addition to variables, Sass gives us more value types like <a target="_blank" href="https://sass-lang.com/documentation/values/maps">Maps</a>, which function sort of like an object, and <a target="_blank" href="https://sass-lang.com/documentation/values/lists">Lists</a>, which are kind of like arrays.</p>
<p><a target="_blank" href="https://sass-lang.com/documentation/values">Learn more about the value types in Sass.</a></p>
<h3 id="heading-more">More</h3>
<p>There are a ton of features available in Sass and lots of articles that cover the most used features. Take some time to explore the documentation and find what’s out there!</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">🐦 Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">📺 Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">📫 Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">💝 Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ VS Code Extensions That'll Boost Your Development Productivity ]]>
                </title>
                <description>
                    <![CDATA[ Having a good text or code editor that fits into your workflow is crucial to productivity as a developer. VS Code comes stocked with a lot of features by default, but here are 7 extensions that will help take your workflow up another level. What is ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/vs-code-extensions-to-boost-your-development-productivity/</link>
                <guid isPermaLink="false">66b8e38c6a98b2a27ee1f352</guid>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Visual Studio Code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Mon, 28 Dec 2020 14:50:40 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/12/vscode.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Having a good text or code editor that fits into your workflow is crucial to productivity as a developer. VS Code comes stocked with a lot of features by default, but here are 7 extensions that will help take your workflow up another level.</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-vs-code">What is VS Code?</a></li>
<li><a class="post-section-overview" href="#heading-vs-code-extensions">VS Code Extensions</a></li>
<li><a class="post-section-overview" href="#heading-sublime-text-keymap-and-settings-importer">Sublime Text Keymap and Settings Importer</a></li>
<li><a class="post-section-overview" href="#heading-import-cost">Import Cost</a></li>
<li><a class="post-section-overview" href="#heading-indent-rainbow">indent-rainbow</a></li>
<li><a class="post-section-overview" href="#heading-rainbow-brackets">Rainbow Brackets</a></li>
<li><a class="post-section-overview" href="#heading-settings-sync">Settings Sync</a></li>
<li><a class="post-section-overview" href="#heading-profile-switcher">Profile Switcher</a></li>
<li><a class="post-section-overview" href="#heading-better-comments">Better Comments</a></li>
<li><a class="post-section-overview" href="#heading-duplicate-action">Duplicate Action</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/OIWVJj9yRbA" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-vs-code">What is VS Code?</h2>
<p>A quick note in case you’re not familiar. <a target="_blank" href="https://code.visualstudio.com/">VS Code</a>, which is short for Visual Studio Code, is a popular text or code editor that’s maintained by the Microsoft team.</p>
<p>It’s grown a tremendous share of the developer market over the last year or two making it the go-to editor for web developers.</p>
<p>Coupled with the fact that Microsoft is investing a lot of time into it and independent developers are building a ton of extensions, you can’t go wrong with giving it a shot.</p>
<h2 id="heading-vs-code-extensions">VS Code Extensions</h2>
<p>Part of what makes VS Code great is it’s extensibility. It allows developers to creatively take the editor to another level by implementing features Microsoft may not want to support or even building a whole note-taking experience on top of it with <a target="_blank" href="https://foambubble.github.io/foam/">Foam</a>.</p>
<p>While there are thousands of extensions available in the <a target="_blank" href="https://marketplace.visualstudio.com/vscode">VS Code Marketplace</a>, these are the 7 that are critical to my workflow as an active developer.</p>
<h2 id="heading-sublime-text-keymap-and-settings-importer">Sublime Text Keymap and Settings Importer</h2>
<p>Before moving to VS Code, I was a Sublime Text 3 user. It’s still a great text editor, but when moving to VS Code, a lot of the shortcuts and key mappings weren’t the same.</p>
<p>Sublime Text Keymap and Settings Importer let me first import my settings from Sublime text, but it also set up the default key mappings. This made shortcuts that were available in Sublime immediately available in VS Code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/vscode-sublime-keyboard-shortcuts.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Sublime Text key mappings in VS Code</em></p>
<p>This includes two of my favorites like multi-select (selecting something then pressing CMD+D / Ctrl+D) and duplicating a line (adding a cursor on a line and pressing CMD+Shift+D / Ctrl+Shift+D).</p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.sublime-keybindings">Sublime Text Keymap and Settings Importer</a> (marketplace.visualstudio.com)</p>
<h2 id="heading-import-cost">Import Cost</h2>
<p>Modern day developers have to constantly deal with dependencies coming from various sources. As we pull in a bunch of different code to build our project, that additional code comes at a cost.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/vscode-import-cost.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Showing import size in VS Code</em></p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost">Import Cost</a> calculates an estimate of the size of an import allowing us to see how much additional weight we would be adding to our project size with that added dependency.</p>
<p>This helps us recognize the size of our dependencies, preventing accidental overload of huge libraries that could impact performance and hurt our customer’s user experience.</p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost">Import Cost</a> (marketplace.visualstudio.com)</p>
<h2 id="heading-indent-rainbow">indent-rainbow</h2>
<p>Style is an important factor in making our code readable. Part of that style is how we indent our code, so we understand nesting of different code blocks.</p>
<p>The issue is sometimes that nesting can grow pretty large and it can be difficult to try to find which opening tag belongs to which closing tag.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/vscode-indent-rainbow.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Rainbow-colored indent spacing in VS Code</em></p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow">indent-rainbow</a> adds colors to the indent spaces, allowing us to easily line up and see which tags belong to each other.</p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow">indent-rainbow</a>  (marketplace.visualstudio.com)</p>
<h2 id="heading-rainbow-brackets">Rainbow Brackets</h2>
<p>Similar to indenting, complex code, particularly when using math, can create easily confusing lines of code when you have multiple uses of parenthesis within the same statement.</p>
<p>For instance, if we want to apply some simple math:</p>
<pre><code><span class="hljs-keyword">const</span> value = (((<span class="hljs-number">1</span>+<span class="hljs-number">1</span>)*<span class="hljs-number">2</span>)+<span class="hljs-number">1</span>)*<span class="hljs-number">2</span>;
</code></pre><p>And while that’s a simple example, that can easily get out of hand and hard to track.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/vscode-rainbow-brackets.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Rainbow-colored brackets in VS Code</em></p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=2gua.rainbow-brackets">Rainbow Brackets</a> highlights the parenthesis in different colors allowing us to get a better idea which opening bracket belongs to which closing bracket of our equation.</p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=2gua.rainbow-brackets">Rainbow Brackets</a> (marketplace.visualstudio.com)</p>
<h2 id="heading-settings-sync">Settings Sync</h2>
<p>If you typically work between two laptops or two different environments, you might have to manually maintain keeping your text editor the same, if you’re particular about your setup (like I am).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/vscode-settings-sync.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Configuration for Settings Sync in VS Code</em></p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync">Settings Sync</a> allows you to save your VS Code settings in a GitHub Gist. This lets you sync those settings across different VS Code installations</p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync">Settings Sync</a> (marketplace.visualstudio.com)</p>
<p><em>Note: if you want to learn more, <a target="_blank" href="https://www.freecodecamp.org/news/how-to-sync-vs-code-settings-between-multiple-devices-and-environments/">I wrote a tutorial</a> that walks you through setting this up step-by-step!</em> </p>
<h2 id="heading-profile-switcher">Profile Switcher</h2>
<p>As a content creator, I need to make sure that when I’m showing my screen to others, that I’m using accessible colors and font sizes that allow people to easily see what I'm demo'ing.</p>
<p>The issue is those settings aren’t what I like to use day-to-day when I’m heads down coding.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/vscode-profile-switcher.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Switching profiles in VS Code</em></p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=aaronpowell.vscode-profile-switcher">Profile Switcher</a> allows you to set up multiple VS Code profiles each with their own configuration allowing you to easily switch between different setups.</p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=aaronpowell.vscode-profile-switcher">Profile Switcher</a> (marketplace.visualstudio.com)</p>
<h2 id="heading-better-comments">Better Comments</h2>
<p>While they might not seem important when you’re writing code, comments are critical to helping others understand that code. They also typically help you understand it when you look at it a year down the road.</p>
<p>Those comments are helpful, but they can be hard to read, as they’re typically all one gray color that doesn’t necessarily stand out.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/vscode-better-comments.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Keyword highlighting of comment blocks in VS Code</em></p>
<p>That’s where <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments">Better Comments</a> comes in, which adds a kind of syntax highlighting to the comments, adding color to keywords and statements that helps the readability of your code comments.</p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments">Better Comments</a> (marketplace.visualstudio.com)</p>
<h2 id="heading-duplicate-action">Duplicate Action</h2>
<p>This last one seems like a small thing, but for some reason, VS Code doesn’t come with the ability to right click a file and duplicate it by default.</p>
<p>When I’m heads down in code, I’ll typically duplicate a file, like an existing template, which allows me to only change the content. This makes creating a new page more productive.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/vscode-duplicate-action.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Duplicate file or directory option in VS Code</em></p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-duplicate">Duplicate Action</a> simply adds the Duplicate File or Folder option to the context menu when you right click a file or folder.</p>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-duplicate">Duplicate Action</a> (marketplace.visualstudio.com)</p>
<h2 id="heading-whats-your-favorite-extension">What’s your favorite extension?</h2>
<p>There are a ton of extensions out there that do amazing things – what’s your favorite? Let me know by <a target="_blank" href="https://twitter.com/colbyfayock">sharing with me on Twitter</a>!</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">🐦 Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">📺 Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">📫 Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">💝 Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to run Visual Regression Testing on a Next.js App with Cypress and Applitools ]]>
                </title>
                <description>
                    <![CDATA[ A critical component of any development project is the tests that make sure that project is always doing exactly what it’s supposed to be doing.  There are a ton of testing tools available to us, but not all of them test what someone actually experie... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-run-visual-regression-testing-on-a-next-js-app-with-cypress-and-applitools/</link>
                <guid isPermaLink="false">66b8e3646a98b2a27ee1f34c</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ user testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 10 Dec 2020 16:14:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/12/applitools.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A critical component of any development project is the tests that make sure that project is always doing exactly what it’s supposed to be doing. </p>
<p>There are a ton of testing tools available to us, but not all of them test what someone actually experiences. How can we use Applitools to visually test our project and make sure it’s actually working right?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-visual-regression-testing">What is Visual Regression Testing?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-cypress">What is Cypress?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-applitools">What is Applitools?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-step-0-creating-a-new-react-application-with-nextjs">Step 0: Creating a new React application with Next.js</a></li>
<li><a class="post-section-overview" href="#heading-step-1-installing-and-configuring-cypress-in-a-nextjs-app">Step 1: Installing and configuring Cypress in a Next.js app</a></li>
<li><a class="post-section-overview" href="#heading-step-2-creating-your-first-cypress-test-in-a-nextjs-app">Step 2: Creating your first Cypress test in a Next.js app</a></li>
<li><a class="post-section-overview" href="#heading-step-3-installing-and-configuring-applitools-eyes">Step 3: Installing and configuring Applitools Eyes</a></li>
<li><a class="post-section-overview" href="#heading-step-4-visual-regression-testing-with-applitools-eyes">Step 4: Visual regression testing with Applitools Eyes</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/3dF4t56LHhs" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>You can also check out <a target="_blank" href="https://www.youtube.com/watch?v=Bei0Cvu7D7I">my live stream</a> from <a target="_blank" href="https://twitch.tv/colbyfayock">my Twitch channel</a> where I walked through the entire process of setting up a new app and testing it with Cypress and Applitools.</p>
<p>And full disclosure, I recently accepted a job as a Developer Advocate with Applitools. But you can do this tutorial using its free tier, with no credit card required.</p>
<h2 id="heading-what-is-visual-regression-testing">What is Visual Regression Testing?</h2>
<p>Similar to most tests, Visual Regression Testing is a type of test that will run periodically and at various stages of a project’s lifecycle like on pull request or production deployment to make sure everything in the app is functioning properly.</p>
<p>What Visual Regression Testing does differently, though, is it directly compares visual snapshots of your project. It detects any changes in content, layout, or any other detail you’d like either by statically visiting a page or interacting with it to preview the result of that interaction.</p>
<h2 id="heading-what-is-cypress">What is Cypress?</h2>
<p><a target="_blank" href="https://www.cypress.io/">Cypress</a> is a JavaScript-based testing framework that we’ll use to run our test suite. It runs tests in the browser, allowing us to directly check the state of our project where people will actually use it.</p>
<p>The great thing about Cypress is it also provides the ability to interact with the page. For instance, if we want to test that someone using our app is able to log in, we can enter credentials and submit the login form, then check that the authentication process properly worked.</p>
<h2 id="heading-what-is-applitools">What is Applitools?</h2>
<p><a target="_blank" href="https://info.applitools.com/ucXr9">Applitools</a> is a visual testing tool and automation platform that lets us visually compare our app at different points in time, giving us the ability to check if something changed or isn’t functioning properly.</p>
<p>While Applitools has a few different features we can take advantage of, we’re going to focus on using the Eyes API, which we’ll use to capture our snapshot and send it up to the Applitools dashboard.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>While we can really run Cypress and Applitools on a <a target="_blank" href="https://info.applitools.com/ucXsd">variety of project types</a>, we’re going to use Next.js to quickly spin up a new <a target="_blank" href="https://reactjs.org/">React</a> application. This will allow us to focus on the testing tools rather than the app itself.</p>
<p>Once we have our app set up, we’ll install Cypress and Applitools so we can use them to run our visual regression testing.</p>
<p><em>Note: you’ll need to have an Applitools account in order to set up visual regression testing. You can <a target="_blank" href="https://info.applitools.com/ucXsg">sign up for a free account</a> at applitools.com.</em></p>
<h2 id="heading-step-0-creating-a-new-react-application-with-nextjs">Step 0: Creating a new React application with Next.js</h2>
<p>To get started, we’re going to use <a target="_blank" href="https://nextjs.org/docs/api-reference/create-next-app">Create Next App</a> to create a new Next.js app.</p>
<p>Once you’re in the directory that you want to create your new project in, inside of your terminal run:</p>
<pre><code>npx create-next-app my-testing-app
</code></pre><p><em>Note: you can change the project name from <code>my-testing-app</code> to whatever you would like.</em></p>
<p>This will clone the default Next.js example from GitHub, install the dependencies, and immediately allow us to get productive with our testing tools.</p>
<p>Once it’s finished, navigate into your new project:</p>
<pre><code>cd my-testing-app
</code></pre><p>Start your development server:</p>
<pre><code>npm run dev
</code></pre><p>And now your site should be available at <a target="_blank" href="http://localhost:3000">http://localhost:3000</a>!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/new-nextjs-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js App</em></p>
<h2 id="heading-step-1-installing-and-configuring-cypress-in-a-nextjs-app">Step 1: Installing and configuring Cypress in a Next.js app</h2>
<p>Now that we have our app set up, we want to install Cypress so that we can use it to run our tests.</p>
<p>Back inside of our terminal, we can install Cypress with:</p>
<pre><code>npm install cypress --save-dev
</code></pre><p>Here, we’re including the <code>—save-dev</code> flag, as we don’t need Cypress to run in the production version of our application, so we install it as a dev dependency.</p>
<p>Once that’s complete, we need a way to run Cypress from the command line. While we can navigate to Cypress itself, we can instead add a new script command, which will make it easier to run Cypress.</p>
<p>Inside of <code>package.json</code>, under <code>scripts</code>, add the following:</p>
<pre><code class="lang-json"><span class="hljs-string">"cy:open"</span>: <span class="hljs-string">"cypress open"</span>
</code></pre>
<p>Now, inside our terminal, we can run that script to open Cypress:</p>
<pre><code>npm run cy:open
</code></pre><p>If this is the first time you’re running Cypress, it might take an extra second and install Cypress in your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/opening-cypress-in-terminal.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Opening Cypress for the first time</em></p>
<p>Once finished, Cypress will open a new dialogue panel that will serve as your dashboard for running tests for your project.</p>
<p>You’ll also notice that Cypress lets you know they also added a new directory to your project at <code>cypress</code>. This includes example files that let you see how Cypress works and immediately get started.</p>
<p>To try this out, on the right side of the Cypress panel, click <strong>Run 19 integration specs</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/cypress-run-all-tests.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Cypress will then open up a new browser and run through all of the example tests.</p>
<p>Next, we’ll add some of our own tests.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-testing-app/commit/ba73974d4521443d64fa4bddbc07500c0bb7b74f">Follow along with the commit!</a></p>
<h2 id="heading-step-2-creating-your-first-cypress-test-in-a-nextjs-app">Step 2: Creating your first Cypress test in a Next.js app</h2>
<p>Now that we can successfully run our tests, let’s try adding our own.</p>
<p>We don’t need really any of the tests that Cypress included in the examples, so let’s remove the entire <code>integration/examples</code> directory.</p>
<p>Then, create a new file under <code>integration</code> called <code>home.spec.js</code> and inside add the following:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/// &lt;reference types="cypress" /&gt;</span>

context(<span class="hljs-string">'Home'</span>, <span class="hljs-function">() =&gt;</span> {
  beforeEach(<span class="hljs-function">() =&gt;</span> {
    cy.visit(<span class="hljs-string">'http://localhost:3000'</span>);
  });

  it(<span class="hljs-string">'should find the title of the homepage'</span>, <span class="hljs-function">() =&gt;</span> {
    cy.get(<span class="hljs-string">'h1'</span>).contains(<span class="hljs-string">'Welcome'</span>);
  });
});
</code></pre>
<p>In the code above, we’re:</p>
<ul>
<li>First adding Cypress as a reference type, which allows Cypress to find the file and know that it should use it to run a test</li>
<li>Creating a new context for our test and defining it as Home</li>
<li>Telling Cypress that before each test, we want it to visit our homepage</li>
<li>Defining a test that grabs the h1 and checks that it contains “Welcome”</li>
</ul>
<p>If we now look back at Cypress, we’ll see that we only have that one Integration Test. If we click it and try to run the test, we’ll see that we actually get an error, as we never started up our development server, meaning it’s not available.</p>
<p>To fix this, we’re going to use a tool called <a target="_blank" href="https://www.npmjs.com/package/start-server-and-test">start-server-and-test</a>.</p>
<p>This package will do what the name implies, it will:</p>
<ul>
<li>Start our server based on the command we provide</li>
<li>Run the tests that we provide</li>
<li>Stop the server once complete</li>
</ul>
<p>To add it, inside of our terminal let’s run:</p>
<pre><code>npm install start-server-and-test --save-dev
</code></pre><p>Then, inside of our <code>package.json</code> file, we’re going to add another new command to the <code>scripts</code> object:</p>
<pre><code class="lang-json"><span class="hljs-string">"test"</span>: <span class="hljs-string">"start-server-and-test dev 3000 cy:open"</span>
</code></pre>
<p>Here, we’re telling start-server-and-test that we want to run the <code>dev</code> command to start our server, that it will be available at port 3000, and that we want to run the <code>cy:open</code> command after to run our tests.</p>
<p>And if we go back to our terminal and run:</p>
<pre><code>npm run test
</code></pre><p>We’ll see that Cypress opens up like before. But if we now run our test, we can see that it successfully opens up our Next.js app and it sees the word “Welcome” inside of our <code>h1</code>!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/successful-test-cypress.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Successfully running a test in Cypress</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-testing-app/commit/b7fdcada3c6642521baa8c34949c4b9df3e56c18">Follow along with the commit</a>.</p>
<h2 id="heading-step-3-installing-and-configuring-applitools-eyes">Step 3: Installing and configuring Applitools Eyes</h2>
<p>With Cypress successfully running our tests, we can now hook into our tests and use Applitools to run visual regression testing on our project.</p>
<p>Before we dive in, make sure you have a <a target="_blank" href="https://info.applitools.com/ucXsg">free account</a> set up over at Applitools, which we’ll need in order to set up an API key.</p>
<p>To get started, we’re going to need to install the Eyes library to our project.</p>
<p>In our terminal, we can run:</p>
<pre><code>npm install @applitools/eyes-cypress --save-dev
</code></pre><p>Which will install the <a target="_blank" href="https://www.npmjs.com/package/@applitools/eyes-cypress">Cypress-specific SDK for Applitools Eyes</a>.</p>
<p>Once that’s finished installing, we can run the Eyes setup script.</p>
<pre><code>npx eyes-setup
</code></pre><p>This will go through the project and add the necessary configurations to Cypress to make Eyes work properly.</p>
<p>Finally, we’ll need to make our Applitools API key available whenever we run our tests.</p>
<p>To start, we need to find our API key in our Applitools account.</p>
<p>Inside the Applitools dashboard, select <strong>My API Key</strong> under the account dropdown.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/applitools-finding-api-key.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Finding the Applitools API key</em></p>
<p>It will open a dialogue where you can select and copy your API key.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/applitools-api-key.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Copying the Applitools API key</em></p>
<p>You’ll want to save this API key for later when we run our tests.</p>
<p>Next, we’ll want to be able to set our API key. We can do this a few ways:</p>
<ul>
<li><a target="_blank" href="https://docs.cypress.io/guides/guides/environment-variables.html#Option-3-CYPRESS">Export the environment variable</a> in our shell before running the tests</li>
<li>Prepend the API key to the test command</li>
<li>Add the API key to the <a target="_blank" href="https://www.npmjs.com/package/@applitools/eyes-cypress#advanced-configuration">applitools.config.js</a> file</li>
<li>Create an environment variable using dotenv and the <a target="_blank" href="https://github.com/morficus/cypress-dotenv">cypres-dotenv</a> package</li>
</ul>
<p>For this demo, we’re going to run our test by prepending the API key to our command. This will allow us to quickly test this out.</p>
<p>To do this, any time we run a command like <code>npm run test</code>, we’re going to include our API key in front of it like:</p>
<pre><code>APPLITOOLS_API_KEY=<span class="hljs-string">"abcd1234"</span> npm run test
</code></pre><p><em>Note: remember to replace the API key with your unique ID.</em></p>
<p>And now, we should be ready to add our first test.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-testing-app/commit/0b11b0238270b320969ac9982b271a48981634f4">Follow along with the commit!</a></p>
<h2 id="heading-step-4-visual-regression-testing-with-applitools-eyes">Step 4: Visual regression testing with Applitools Eyes</h2>
<p>We have Cypress and Applitools both configured and ready to go, meaning we can now add Applitools Eyes to visually test our app!</p>
<p>Our app doesn’t have a lot of functionality yet., so we can start off with a basic check that makes sure our homepage looks the way it’s supposed to each time our tests run.</p>
<p>To start, inside of our <code>cypres/integrations/home.spec.js</code> file, let’s add the following right below our existing <code>it</code> statement:</p>
<pre><code class="lang-javascript">it(<span class="hljs-string">'should verify the homepage looks as expected'</span>, <span class="hljs-function">() =&gt;</span> {
  cy.eyesOpen({
    <span class="hljs-attr">appName</span>: <span class="hljs-string">'My App'</span>,
    <span class="hljs-attr">testName</span>: <span class="hljs-string">'Homepage Check'</span>,
  });

  cy.eyesCheckWindow({
    <span class="hljs-attr">tag</span>: <span class="hljs-string">'App Window'</span>,
    <span class="hljs-attr">target</span>: <span class="hljs-string">'window'</span>,
    <span class="hljs-attr">fully</span>: <span class="hljs-literal">true</span>
  });

  cy.eyesClose();
});
</code></pre>
<p>Here’s what we’re doing here:</p>
<ul>
<li>First, we’re “opening the eyes” of Applitools, which will prepare the Eyes functionality to check our app</li>
<li>Next, we’re running a check on the window of our application, essentially capturing a screenshot of our app and sending it to Applitools</li>
<li>Finally, we “close the eyes” of Applitools, letting Eyes know that we’re running our checks</li>
</ul>
<p>Now, if we run our test command and start our test:</p>
<pre><code>APPLITOOLS_API_KEY=<span class="hljs-string">"abcd1234"</span> npm run test
</code></pre><p>We can see that Cypress runs our new test case which doesn’t appear that it’s doing anything inside of our browser, but shows a passing indicator.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/successul-applitools-check.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Successfully ran an Applitools Eyes check in Cypress</em></p>
<p>Now, if we go back to our Applitools dashboard:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/applitools-eyes-first-snapshot.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>First snapshot in Applitools</em></p>
<p>We can see that we have a new “run” titled Homepage Check (which we specified in the code) which shows that it passed with a snapshot of our app.</p>
<p>Now, having this screenshot alone isn’t what makes this powerful. From now on, any time we run this test, Applitools will compare our app against this original snapshot and let us know if anything changed.</p>
<p>To test this out, we’re going to change the color of title of our page. This might seem like a simple change, but style changes can be more challenging for tools like Cypress alone to detect an issue, which is where Applitools Eyes will shine with its snapshot comparison.</p>
<p>Inside of <code>styles/Home.module.css</code> file, let’s add the following to the <code>.title</code> class:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">color</span>: <span class="hljs-selector-id">#ddd</span>;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/nextjs-app-title-color-change.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app with light gray title</em></p>
<p>While we may not have intentionally made a change like this in practice, this could have happened if we were changing styles that cascade to our title. This makes our title hard to read, but that makes this perfect for a test case.</p>
<p>Now, let’s run our tests again:</p>
<pre><code>APPLITOOLS_API_KEY=<span class="hljs-string">"abcd1234"</span> npm run test
</code></pre><p>But this time, we can see that our test fails! </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/cypress-failed-applitools-eyes-test-error.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Cypress throwing an error with the Applitools Eyes check</em></p>
<p>Our Applitools test fails because it states that “Eyes-Cypress detected diffs or errors during execution of visual tests”.</p>
<p>If we look inside of our Applitools dashboard:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/applitools-eyes-text-change-detected.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Change detected in text of app title in Applitools Eyes</em></p>
<p>We can see that we now have an “Unresolved” run where Applitools shows us the differences on the page, which in our case, is the "Welcome to" part of our title.</p>
<p>This is super useful when working on projects where it can be challenging to test every single page or type of page in an app. We can make sure that if anything changes or breaks, it will immediately get flagged in Applitools.</p>
<p>From here, if we’re happy with color change, we can accept the new version of our app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/applitools-eyes-accept-reject-changes.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Accept or reject changes in Applitools Eyes</em></p>
<p>Otherwise we can reject it and let our team know that it needs to be fixed.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-testing-app/commit/6c5f5655d0e15878e870a893652201979244e986">Follow along with the commit!</a></p>
<h2 id="heading-whats-next">What’s next?</h2>
<p>Between Cypress and Applitools, we have a lot of things we can do to make sure that our app is behaving the way we want it to.</p>
<p>Most of the time when we’re building an app, we’re building that app so people can interact with it.</p>
<p>Using Cypress, we can click on different parts of the page, changing the state of the page, then run a check with Applitools Eyes to make sure it’s functioning the way we expect it to.</p>
<p>We can also have Cypress run on different browsers to make sure our app is working properly everywhere someone is trying to use it!</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">🐦 Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">📺 Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">📫 Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">💝 Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Fetch GraphQL Data in Next.js with Apollo GraphQL ]]>
                </title>
                <description>
                    <![CDATA[ Next.js has been steadily growing as a must-have tool for developers creating React apps. Part of what makes it great is its data fetching APIs that request data for each page. But how can we use that API to make GraphQL queries for our app? What is... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-fetch-graphql-data-in-next-js-with-apollo-graphql/</link>
                <guid isPermaLink="false">66b8e35d0cedc1f2a4f7069d</guid>
                
                    <category>
                        <![CDATA[ Apollo GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 01 Dec 2020 16:22:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/11/apollo.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Next.js has been steadily growing as a must-have tool for developers creating React apps. Part of what makes it great is its data fetching APIs that request data for each page. But how can we use that API to make GraphQL queries for our app?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-graphql">What is GraphQL?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-apollo-graphql">What is Apollo GraphQL?</a></li>
<li><a class="post-section-overview" href="#heading-fetching-data-in-nextjs">Fetching data in Next.js</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-step-0-creating-a-new-nextjs-app">Step 0: Creating a new Next.js app</a></li>
<li><a class="post-section-overview" href="#heading-step-1-adding-apollo-graphql-to-a-nextjs-app">Step 1: Adding Apollo GraphQL to a Next.js app</a></li>
<li><a class="post-section-overview" href="#heading-step-2-adding-data-to-a-nextjs-page-with-getstaticprops">Step 2: Adding data to a Next.js page with getStaticProps</a></li>
<li><a class="post-section-overview" href="#heading-step-3-fetch-data-with-a-graphql-query-in-nextjs-using-apollo-client">Step 3: Fetch data with a GraphQL query in Next.js using Apollo Client</a></li>
<li><a class="post-section-overview" href="#heading-step-4-adding-spacex-launch-data-to-the-page">Step 4: Adding SpaceX launch data to the page</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/oxUPXhZ1t9I" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-graphql">What is GraphQL?</h2>
<p><a target="_blank" href="https://graphql.org/">GraphQL</a> is a query language and runtime that provides a different way of interacting with an API than what you would expect with a traditional REST API.</p>
<p>When fetching data, instead of making a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET">GET</a> request to a URL to grab that data, GraphQL endpoints take a “query”. That query consists of what data you want to grab, whether it’s an entire dataset or a limited portion of it.</p>
<p>If your data looks something like this:</p>
<pre><code>Movie {
  <span class="hljs-string">"title"</span>: <span class="hljs-string">"Sunshine"</span>,
  <span class="hljs-string">"releaseYear"</span>: <span class="hljs-string">"2007"</span>,
  <span class="hljs-string">"actors"</span>: [...],
  <span class="hljs-string">"writers"</span>: [...]
}
</code></pre><p>And you only want to grab the title and the year it was released, you could send in a query like this:</p>
<pre><code>Movie {
  title
  releaseYear
}
</code></pre><p>Grabbing only the data you need.</p>
<p>The cool thing is, you can also provide complex relationships between the data. With a single query, you could additionally request that data from different parts of the database that would traditionally take multiple requests with a REST API.</p>
<h2 id="heading-what-is-apollo-graphql">What is Apollo GraphQL?</h2>
<p><a target="_blank" href="https://www.apollographql.com/">Apollo GraphQL</a> at its core is a GraphQL implementation that helps people bring together their data as a graph.</p>
<p>Apollo also provides and maintains a GraphQL client, which is what we’re going to use, that allows people to programmatically interact with a GraphQL API.</p>
<p>Using Apollo’s GraphQL client, we’ll be able to make requests to a GraphQL API similar to what we would expect with a REST-based request client.</p>
<h2 id="heading-fetching-data-in-nextjs">Fetching data in Next.js</h2>
<p>When fetching data with Next.js, you have a few options for how you want to fetch that data.</p>
<p>First, you could go the client side route and make the request once the page loads. The issue with this is that you’re then putting the burden on the client to take the time to make those requests.</p>
<p>The Next.js APIs like <code>getStaticProps</code> and <code>getServerSideProps</code> allow you to collect data at different parts of the lifecycle, giving us the opportunity to <a target="_blank" href="https://www.youtube.com/watch?v=6ElI2ZJ4Uro">make a completely static app</a> or one that’s server-side rendered. That will serve the data already rendered to the page straight to the browser.</p>
<p>By using one of those methods, we can request data along with our pages and inject that data as props right into our app.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’re going to create a Next.js app that shows the latest launches from SpaceX.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/spacex-launches-demo.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>SpaceX launches demo</em></p>
<p>We’ll use the API maintained by <a target="_blank" href="https://spacex.land/">SpaceX Land</a> to make a GraphQL query that grabs the last 10 flights. Using <a target="_blank" href="https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation">getStaticProps</a>, we’ll make that request at build time, meaning our page will be rendered statically with our data.</p>
<h2 id="heading-step-0-creating-a-new-nextjs-app">Step 0: Creating a new Next.js app</h2>
<p>Using Create Next App, we can quickly spin up a new Next.js app that we can use to immediately start diving into the code.</p>
<p>Inside your terminal, run the command:</p>
<pre><code>npx create-next-app my-spacex-launches
</code></pre><p><em>Note: you don’t have to use <code>my-spacex-app</code>, feel free to replace that with whatever name you want to give the project.</em></p>
<p>After running that script, Next.js will set up a new project and install the dependencies.</p>
<p>Once finished, you can start up your development server:</p>
<pre><code>cd my-spacex-launches
npm run dev
</code></pre><p>This will start a new server at <a target="_blank" href="http://localhost:3000">http://localhost:3000</a> where you can now visit your new app!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/new-nextjs-app-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js app</em></p>
<h2 id="heading-step-1-adding-apollo-graphql-to-a-nextjs-app">Step 1: Adding Apollo GraphQL to a Next.js app</h2>
<p>To get started with making a GraphQL query, we’ll need a GraphQL client. We’ll use the Apollo GraphQL Client to make our queries to the SpaceX GraphQL server.</p>
<p>Back inside of the terminal, run the following command to install our new dependencies:</p>
<pre><code>npm install @apollo/client graphql
</code></pre><p>This will add the Apollo Client as well as GraphQL, which we’ll need to to form the GraphQL query.</p>
<p>And once installation completes, we’ll be ready to get started Using Apollo Client.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-spacex-launches/commit/0fcc3a0141e7bfb795c3c91c355fdfc459a17332">Follow along with the commit!</a></p>
<h2 id="heading-step-2-adding-data-to-a-nextjs-page-with-getstaticprops">Step 2: Adding data to a Next.js page with getStaticProps</h2>
<p>Before we fetch any data with Apollo, we’re going to set up our page to be able to request data then pass that data as a prop to our page at build time.</p>
<p>Let’s define a new function at the bottom of the page below our <code>Home</code> component called <code>getStaticProps</code>:</p>
<pre><code><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">getStaticProps</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Code will go here</span>
}
</code></pre><p>When Next.js builds our app, it knows to look for this function. So when we export it, we’re letting Next.js know we want to run code in that function.</p>
<p>Inside our <code>getStaticProps</code> function, we’re going to be ultimately returning our props to the page. To test this out, let’s add the following to our function:</p>
<pre><code><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">getStaticProps</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: {
      <span class="hljs-attr">launches</span>: []
    }
  }
}
</code></pre><p>Here, we’re passing a new prop of <code>launches</code> and setting it to an empty array.</p>
<p>Now, back inside of our <code>Home</code> component, let’s add a new destructured argument that will serve as our prop along with a <code>console.log</code> statement to test our new prop:</p>
<pre><code><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">{ launches }</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'launches'</span>, launches);
</code></pre><p>If we reload the page, we can see that we’re now logging out our new prop <code>launches</code> which includes an empty array just like we defined.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/nextjs-console-log-launches-array.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Logging launches prop</em></p>
<p>The great thing about this is that given that the <code>getStaticProps</code> function we’re creating is asynchronous, we can make any request we’d like (including a GraphQL query) and return it as props to our page, which is what we’ll do next.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-spacex-launches/commit/868a4f6b31200cd2407b4aa2fe37a243fc235932">Follow along with the commit!</a></p>
<h2 id="heading-step-3-fetch-data-with-a-graphql-query-in-nextjs-using-apollo-client">Step 3: Fetch data with a GraphQL query in Next.js using Apollo Client</h2>
<p>Now that our application is prepared to add props to the page and we have Apollo installed, we can finally make a request to grab our SpaceX data.</p>
<p>Here, we’re going to use the Apollo Client, which will allow us to interface with the SpaceX GraphQL server. We’ll make our request to the API using the Next.js getStaticProps method, allowing us to dynamically create props for our page when it builds.</p>
<p>First, let’s import our Apollo dependencies into the project. At the top of the page add:</p>
<pre><code><span class="hljs-keyword">import</span> { ApolloClient, InMemoryCache, gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>;
</code></pre><p>This is going to include the Apollo Client itself, <code>InMemoryCache</code> which allows Apollo to optimize by reading from cache, and <code>gql</code> which we’ll use to form our GraphQL query.</p>
<p>Next, to use the Apollo Client, we need to set up a new instance of it.</p>
<p>Inside the top of the <code>getStaticProps</code> function, add:</p>
<pre><code><span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApolloClient({
  <span class="hljs-attr">uri</span>: <span class="hljs-string">'https://api.spacex.land/graphql/'</span>,
  <span class="hljs-attr">cache</span>: <span class="hljs-keyword">new</span> InMemoryCache()
});
</code></pre><p>This creates a new Apollo Client instance using the SpaceX API endpoint that we’ll use to query against.</p>
<p>With our client, we can finally make a query. Add the following code below the client:</p>
<pre><code><span class="hljs-keyword">const</span> { data } = <span class="hljs-keyword">await</span> client.query({
  <span class="hljs-attr">query</span>: gql<span class="hljs-string">`
    query GetLaunches {
      launchesPast(limit: 10) {
        id
        mission_name
        launch_date_local
        launch_site {
          site_name_long
        }
        links {
          article_link
          video_link
          mission_patch
        }
        rocket {
          rocket_name
        }
      }
    }
  `</span>
});
</code></pre><p>This does a few things:</p>
<ul>
<li>Creates a new GraphQL query inside of the <code>gql</code> tag</li>
<li>Creates a new query request using <code>client.query</code></li>
<li>It uses <code>await</code> to make sure it finishes the request before continuing</li>
<li>And finally destructures <code>data</code> from the results, which is where the information we need is stored</li>
</ul>
<p>Inside of the GraphQL query, we’re telling the SpaceX API that we want to get <code>launchesPast</code>, which are the previous launches from SpaceX, and we want to get the last 10 of them (limit). Inside that, we define the data we’d like to query.</p>
<p>If we take a second to add a new console log statement after that, we can see what <code>data</code> looks like.</p>
<p>Once you refresh the page though, you’ll notice that you’re not seeing anything inside of the browser’s console.</p>
<p><code>getStaticProps</code> runs during the build process, meaning, it runs in node. Because of that, we can look inside of our terminal and we can see our logs there:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/logging-static-props-terminal.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Logging data to the terminal</em></p>
<p>After seeing that, we know that inside of the <code>data</code> object, we have a property called <code>launchesPast</code>, which includes an array of launch details.</p>
<p>Now, we can update our return statement to use <code>launchesPast</code>:</p>
<pre><code><span class="hljs-keyword">return</span> {
  <span class="hljs-attr">props</span>: {
    <span class="hljs-attr">launches</span>: data.launchesPast
  }
}
</code></pre><p>And if we add our <code>console.log</code> statement back to the top of the page to see what our <code>launches</code> prop looks like, we can see our launch data is now available as a prop to our page:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/logging-static-props-web-console.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Logging props to web console</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-spacex-launches/commit/f273bcde3d2baccd54e4c65930ab499dbe4862ed">Follow along with the commit!</a></p>
<h2 id="heading-step-4-adding-spacex-launch-data-to-the-page">Step 4: Adding SpaceX launch data to the page</h2>
<p>Now for the exciting part!</p>
<p>We have our launch data that we were able to use Apollo Client to request from the SpaceX GraphQL server. We made that request in <code>getStaticProps</code> so that we could make our data available as the <code>launches</code> prop that contains our launch data.</p>
<p>Digging into the page, we’re going to take advantage of what already exists. For instance, we can start by updating the <code>h1</code> tag and the paragraph below it to something that describes our page a little bit better.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/updated-page-title.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Updated page title</em></p>
<p>Next, we can use the already existing link cards to include all of our launch information.</p>
<p>To do this, let’s first add a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a> statement inside of the page’s grid, where the component we return is one of the cards, with launch details filled in:</p>
<pre><code>&lt;div className={styles.grid}&gt;
  {launches.map(<span class="hljs-function"><span class="hljs-params">launch</span> =&gt;</span> {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{launch.id}</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{launch.links.video_link}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.card}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{ launch.mission_name }<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Launch Date:<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span> { new Date(launch.launch_date_local).toLocaleDateString("en-US") }<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>
    );
  })}
</code></pre><p>We can also get rid of the rest of the default Next.js cards including Documentation and Learn.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/list-of-spacex-launches.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Page with SpaceX launches</em></p>
<p>Our page now includes the last 10 launches from SpaceX along with the date of the launch!</p>
<p>We can even click any of those cards, and because we linked to the video link, we can now see the launch video.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-spacex-launches/commit/e35ed076253e3648fa5d8cd62e993e4e9e436396">Follow along with the commit!</a></p>
<h2 id="heading-whats-next">What’s next?</h2>
<p>From here, we can include any additional data from inside of our <code>launches</code> array on our page. The API even includes mission patch images, which we can use to show nice graphics for each launch.</p>
<p>You can even add additional data to the GraphQL query. Each launch has a lot of information available including the launch crew and more details about the rocket.</p>
<p><a target="_blank" href="https://api.spacex.land/graphql/">https://api.spacex.land/graphql/</a></p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://jamstackhandbook.com/">
      <img src="https://www.freecodecamp.org/news/content/images/size/w1600/2020/11/jamstack-handbook-banner.jpg" alt="Jamstack Handbook" width="600" height="400" loading="lazy">
    </a>
  </p>
</div>

<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">🐦 Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">📺 Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">📫 Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">💝 Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Static Site Generation? How Next.js Uses SSG for Dynamic Web Apps ]]>
                </title>
                <description>
                    <![CDATA[ Static websites are as old as the web itself. But the rise of JavaScript has opened the door to make those static sites more dynamic.  While that can include building an HTML file by hand, how can we leverage static generation to build apps with mode... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/static-site-generation-with-nextjs/</link>
                <guid isPermaLink="false">66b8e3886a98b2a27ee1f350</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Static Site Generators ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 18 Nov 2020 17:49:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/11/static-generation.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Static websites are as old as the web itself. But the rise of JavaScript has opened the door to make those static sites more dynamic. </p>
<p>While that can include building an HTML file by hand, how can we leverage static generation to build apps with modern tools?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-static-generation">What is Static Generation?</a></li>
<li><a class="post-section-overview" href="#heading-what-happens-during-static-generation">What happens during Static Generation?</a></li>
<li><a class="post-section-overview" href="#heading-how-does-nextjs-use-static-generation">How does Next.js use Static Generation?</a></li>
<li><a class="post-section-overview" href="#statically-generating-an-app-with-next-js">Statically generating an app with Next.js</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/6ElI2ZJ4Uro" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-static-generation">What is Static Generation?</h2>
<p>Static Generation describes the process of compiling and rendering a website or app at build time. The output is a bunch of static files, including the HTML file itself and assets like JavaScript and CSS.</p>
<p>If you haven’t heard of Static Generation but that concept sounds familiar, you might have heard of it by its longer name Static Site Generation or its acronym SSG.</p>
<h2 id="heading-what-happens-during-static-generation">What happens during Static Generation?</h2>
<p>JavaScript-based web apps as we traditionally know them work by running libraries like React or scripts at run time in the browser. </p>
<p>When the browser receives the page, it’s usually simple HTML without a lot of content. This then loads the scripts to pull the content into the page, a process also known as hydration.</p>
<p>With Static Generation, tools like Next.js try to render that page mostly like it would in the browser but at compile time. This gives us the ability to serve the entire content on first load. The scripts still hydrate the page during this process, but ideally with fewer changes or no changes at all.</p>
<h2 id="heading-how-does-nextjs-use-static-generation">How does Next.js use Static Generation?</h2>
<p>Out of the box, Next.js will attempt to statically generate any pages that it can. It does this by detecting how an app is fetching its data.</p>
<p>Next.js provides a <a target="_blank" href="https://nextjs.org/docs/basic-features/data-fetching">few different APIs to fetch data</a> including <code>getStaticProps</code> and <code>getServerSideProps</code>, which, depending on how they’re used, determines how Next.js will build your app.</p>
<p>If you only use <code>getStaticProps</code> to fetch data, Next.js will fetch that data at build time, leaving you with a completely static page. </p>
<p>If you use <code>getServerSideProps</code>, Next.js will know that the app requires a server to render those pages. </p>
<p>Alongside a deployment solution like Vercel that <a target="_blank" href="https://vercel.com/solutions/nextjs">will automatically handle configuring a server</a>, Next.js will load any of the data when someone requests the page from the server.</p>
<p>While it doesn’t do it by default, Next.js also provides the ability to export the app into static files into a separate directory after the app has been built.</p>
<p>First, you would run the <code>next build</code> command to build the app, then you would run <code>next export</code> which, by default, makes the app available as static files in the <code>out</code> directory.</p>
<h2 id="heading-how-to-statically-generate-an-app-with-nextjs">How to statically generate an app with Next.js</h2>
<p>To get an idea of how this works, we can quickly create a new Next.js app.</p>
<p>The only requirements for this is that you have <a target="_blank" href="https://nodejs.org/en/">Node</a> installed with npm and the ability to use a terminal to run commands.</p>
<h3 id="heading-how-to-create-a-nextjs-app">How to create a Next.js app</h3>
<p>Getting started is as simple as running a single line in the terminal.</p>
<p>Open up the directory you’d like to create your project in and run:</p>
<pre><code>npx create-next-app my-<span class="hljs-keyword">static</span>-nextjs-app
</code></pre><p>After the installation is complete, you can navigate to your new project directory:</p>
<pre><code>cd my-<span class="hljs-keyword">static</span>-nextjs-app
</code></pre><p>Once there, start your development server:</p>
<pre><code>npm run dev
</code></pre><p>And once the server is ready, you can open up <a target="_blank" href="http://localhost:3000">http://localhost:3000</a> in your browser where you can now see your new Next.js app!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/new-nextjs-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js app</em></p>
<h3 id="heading-how-to-build-a-nextjs-app">How to build a Next.js app</h3>
<p>Now that we have our application available, let’s try to build it.</p>
<p>In the same directory, run the command:</p>
<pre><code>npm run build
</code></pre><p>If you look at the output inside of the terminal, we see a few important things happen.</p>
<p>First, Next.js lets us know that it’s running through its build process, including optimizing the app for performance, compiling the app, and collecting data.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/nextjs-build.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Building with Next.js</em></p>
<p>Next, we see that Next.js shows us a breakdown of how it’s built each page.</p>
<p>The default Next.js starting template includes a few static pages and an example API route. </p>
<p>Using the legend at the bottom, we can see that all of the pages and assets were statically generated with one route tagged as requiring a server, which would be our API route.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/nextjs-static-generation.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js generating pages</em></p>
<p><em>Note: For the purposes of this walkthrough, we can ignore the API route, but Next.js along with Vercel provides the ability to build lambda functions as part of the Next.js API.</em></p>
<h3 id="heading-how-to-build-a-static-nextjs-app">How to build a static Next.js app</h3>
<p>With our Next.js build output, we know that we just built some static pages, but we might have trouble finding them. If we look at the folders and files in our project, it’s not immediately clear where those files are.</p>
<p>When Next.js builds an app, by default, it only outputs that app inside the <code>.next</code> directory. This includes configuration files that tools like Vercel can use and understand to deploy the app.</p>
<p>Technically, that directory includes our entire app, but this isn’t something we can easily deploy to static hosting.</p>
<p>Next.js also provides the ability to export an app. This will take the app that we built and produce a set of static files which we can then use to deploy our app.</p>
<p>Inside of the <code>package.json</code> file, update the <code>build</code> script to include <code>next export</code>:</p>
<pre><code><span class="hljs-string">"build"</span>: <span class="hljs-string">"next build &amp;&amp; next export"</span>,
</code></pre><p>Once updated, run the build command again in the project directory:</p>
<pre><code>npm run build
</code></pre><p>And now we can see that not only did we build the app like we did in our last step, Next.js lets us know that we’re also exporting the app that we built into static files.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/nextjs-exporting-static-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Exporting static Next.js app</em></p>
<p>If we look inside of our project folder, we should now see a new directory called <code>out</code>.</p>
<p>If we look inside of that folder, we can now see our entire app statically compiled including the <code>index.html</code> file as well as all of the CSS and JS needed to use the app!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/nextjs-static-output.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-where-can-we-go-from-here">Where can we go from here?</h2>
<p>We learned that we can use Next.js and the concept of Static Generation to statically compile an app. </p>
<p>Tools like Next.js can do this by compiling our code, similar to what we might see in a browser, so that by the time our app hits the browser, it’s all ready to go.</p>
<p>With a simple command, we can also build and compile our app, as well as export it into static files. We can deploy those static files to any static storage service like Vercel or AWS S3. This provides us with an easy way to craft dynamic web apps that are fast and cheap.</p>
<p>Learn more about how Next.js leverages its different APIs to provide both static and dynamic experiences by <a target="_blank" href="https://nextjs.org/docs/basic-features/data-fetching">visiting the Next.js docs</a>.</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://jamstackhandbook.com/">
      <img src="https://www.freecodecamp.org/news/content/images/size/w1600/2020/11/jamstack-handbook-banner.jpg" alt="Jamstack Handbook" width="600" height="400" loading="lazy">
    </a>
  </p>
</div>

<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">🐦 Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">📺 Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">📫 Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">💝 Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Github Actions to Deploy a Next.js Website to AWS S3 ]]>
                </title>
                <description>
                    <![CDATA[ The beauty of Next.js and static web apps is that they let you run the project pretty much anywhere using object storage, like on AWS S3. But it can be a pain to manually update those files each time.  How can we use GitHub Actions to automate and co... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-github-actions-to-deploy-a-next-js-website-to-aws-s3/</link>
                <guid isPermaLink="false">66b8e3759232d58aac300b17</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ continuous deployment ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub Actions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Mon, 02 Nov 2020 19:27:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/actions-s3.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The beauty of Next.js and static web apps is that they let you run the project pretty much anywhere using object storage, like on AWS S3. But it can be a pain to manually update those files each time. </p>
<p>How can we use GitHub Actions to automate and continuously deploy our app to S3?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-github-actions">What are GitHub Actions?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-continuous-deployment">What is Continuous Deployment?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-step-0-setting-up-a-new-nextjs-project-on-github">Step 0: Setting up a new Next.js project on GitHub</a></li>
<li><a class="post-section-overview" href="#heading-step-1-manually-creating-and-deploying-a-nextjs-project-to-a-new-s3-bucket">Step 1: Manually creating and deploying a Next.js project to a new S3 Bucket</a></li>
<li><a class="post-section-overview" href="#heading-step-2-creating-a-new-github-action-workflow-to-automatically-build-a-nextjs-project">Step 2: Creating a new GitHub Action workflow to automatically build a Next.js project</a></li>
<li><a class="post-section-overview" href="#heading-step-3-configuring-a-github-action-to-deploy-a-static-website-to-s3">Step 3: Configuring a GitHub Action to deploy a static website to S3</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/D3h91EvRxuk" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-are-github-actions">What are GitHub Actions?</h2>
<p>GitHub Actions is a free service from GitHub that allows us to automate code tasks.</p>
<p>I <a target="_blank" href="https://www.freecodecamp.org/news/what-are-github-actions-and-how-can-you-automate-tests-and-slack-notifications/">previously wrote about</a> how we can use them to automate tasks like running tests on our code and sending notifications to Slack.</p>
<p>They provide a flexible way to automatically run code based on our existing workflows. This provides a lot of possibilities like even deploying our website!</p>
<h2 id="heading-what-is-aws-s3">What is AWS S3?</h2>
<p><a target="_blank" href="https://aws.amazon.com/s3/">S3</a> (Simple Storage Service) is an object storage service from AWS. It allows you to store files in the cloud easily making them available around the world.</p>
<p>It also allows you to use these files as a website. Because we can upload an HTML file as an object, we can also configure S3 to access that file as an HTTP request. This means that we can <a target="_blank" href="https://www.freecodecamp.org/news/how-to-host-and-deploy-a-static-website-or-jamstack-app-to-s3-and-cloudfront/">host an entire website right in S3</a>.</p>
<h2 id="heading-what-is-continuous-deployment">What is Continuous Deployment?</h2>
<p>Continuous Deployment, often referred to by its acronym CD, is the practice of maintaining code in a releasable state and deploying that code automatically or in short cycles.</p>
<p>Particularly in our use case, we’re going to configure our project so that any time a new update is pushed or merged to the primary Git branch, our website will deploy.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’re first going to bootstrap a simple <a target="_blank" href="https://nextjs.org/">Next.js</a> app using the default Next.js starting template and configure it to compile to static files.</p>
<p>If you don’t want to create a Next.js project, you can follow along with even a simple HTML file and not run any of the build commands. But Next.js is a modern way to build dynamic web apps, so we’ll start there.</p>
<p>With our website files ready to go, we’ll create and configure an S3 bucket in AWS where we’ll host our website.</p>
<p>Finally, we’ll create a new GitHub Action workflow that will automatically update the website files in S3 any time a new change occurs on our primary branch (<code>main</code>).</p>
<h2 id="heading-step-0-setting-up-a-new-nextjs-project-on-github">Step 0: Setting up a new Next.js project on GitHub</h2>
<p>We’re going to get started with the default template with Next.js.</p>
<p>After navigating to the directory you want to create your project in, run:</p>
<pre><code>yarn create next-app my-<span class="hljs-keyword">static</span>-website
# or
npx create-next-app my-<span class="hljs-keyword">static</span>-website
</code></pre><p>Note: Feel free to replace <code>my-static-website</code> with the name of your choice. We’ll use that for the rest of this tutorial.</p>
<p>If you navigate to that directory and run the development command, you should be able to successfully start up your development server.</p>
<pre><code>cd my-<span class="hljs-keyword">static</span>-website
yarn dev
# or
npm run dev
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/10/new-nextjs-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js App</em></p>
<p>Next, let’s configure our project to statically compile.</p>
<p>Inside the <code>package.json</code> file, update the <code>build</code> script to:</p>
<pre><code class="lang-json"><span class="hljs-string">"build"</span>: <span class="hljs-string">"next build &amp;&amp; next export"</span>,
</code></pre>
<p>What this will do is tell Next to take the website and export it to static files, which we’ll use to host the site.</p>
<p>We can test this out by running the command:</p>
<pre><code>yarn build
# or
npm run build
</code></pre><p>And once finished, we can look inside of the <code>out</code> directory and see all of the files of our new website.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nextjs-build-export-output.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Static output from Next.js</em></p>
<p>Finally, we want to host this on GitHub.</p>
<p>Inside of your GitHub account, <a target="_blank" href="https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/create-a-repo">create a new repository</a>. This will then provide instructions on how you can <a target="_blank" href="https://docs.github.com/en/free-pro-team@latest/github/importing-your-projects-to-github/adding-an-existing-project-to-github-using-the-command-line">add an existing project</a> to that repo.</p>
<p>And once you push our your project to GitHub, we should be ready to set up our new website project!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/project-on-github.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New repo in GitHub</em></p>
<p>Follow along with the commits:</p>
<ul>
<li><a target="_blank" href="https://github.com/colbyfayock/my-static-website/commit/ca9e4bca3c37fbd8553b0b183890c32836c35296">Adding the initial Next.js project</a> via <a target="_blank" href="https://nextjs.org/docs/api-reference/create-next-app">Create Next App</a></li>
<li><a target="_blank" href="https://github.com/colbyfayock/my-static-website/commit/7907f4a0fac5f0aed2922202c5f0070dfc055f83">Configuring Next.js to export the project</a></li>
</ul>
<h2 id="heading-step-1-manually-creating-and-deploying-a-nextjs-project-to-a-new-s3-bucket">Step 1: Manually creating and deploying a Next.js project to a new S3 Bucket</h2>
<p>To get started with our new S3 Bucket, first log in to your AWS account and navigate to the S3 service.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/aws-s3-console.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>No buckets in S3</em></p>
<p>We’ll want to create a new bucket, using the name of our choice, which will be used for the S3 endpoint where our website is hosted. We’ll also want to configure our S3 bucket to be able to host a website.</p>
<p><em>Note: this tutorial will not walk you through how to host a website on S3, but you can check out my other tutorial that will <a target="_blank" href="https://www.freecodecamp.org/news/how-to-host-and-deploy-a-static-website-or-jamstack-app-to-s3-and-cloudfront/">walk you through hosting a website on S3</a> step-by-step.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/s3-bucket-website-hosting.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Static website hosting in AWS S3</em></p>
<p>Once we have our S3 bucket configure as a website, we can go back to our Next.js project folder, run our build command, and then upload all of our files from the <code>out</code> directory into our new S3 bucket.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/website-files-in-s3.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>S3 Bucket with Static App</em></p>
<p>And once those files are uploaded and we’ve configured our S3 bucket for website hosting, we should now be able to see our project live on the web!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nextjs-s3-website.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>AWS S3 hosted Next.js app</em></p>
<h2 id="heading-step-2-creating-a-new-github-action-workflow-to-automatically-build-a-nextjs-project">Step 2: Creating a new GitHub Action workflow to automatically build a Next.js project</h2>
<p>To get started, we’re going to need to create a new workflow.</p>
<p>If you’re familiar with GitHub Actions, you could create one manually, but we’ll quickly walk through how to do this in the UI.</p>
<p>Navigate to the Actions tab of your GitHub repository and click on "set up a workflow yourself."</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/github-actions-new-workflow.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New GitHub Action Workflow</em></p>
<p>GitHub provides a starting template that we can use for our workflow, though we’ll want to make some changes.</p>
<p>Let’s do the following:</p>
<ul>
<li>Optional: rename the file to deploy.yml</li>
<li>Optional: rename the workflow to CD (as it’s a bit different from CI)</li>
<li>Optional: remove all of the comments to make it a bit easier to read</li>
<li>Remove the <code>pull_request</code> definition in the <code>on</code> property</li>
<li>Remove all <code>steps</code> except for <code>uses: actions/checkout@v2</code></li>
</ul>
<p>So at this point we should be left with:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">CD</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">main</span> ]

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
</code></pre>
<p>This code alone will trigger a process that spins up a new instance of Ubuntu and simply checks out the code from GitHub any time there’s a new change pushed to the <code>main</code> branch.</p>
<p>Next, once we have our code checked out, we want to build it. This will allow us to take that output and sync it to S3.</p>
<p>This step will differ slightly depending on if you are using yarn or npm for your project.</p>
<p>If you’re using yarn, under the <code>steps</code> definition, add the following:</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v1</span>
  <span class="hljs-attr">with:</span>
    <span class="hljs-attr">node-version:</span> <span class="hljs-number">12</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span> <span class="hljs-string">-g</span> <span class="hljs-string">yarn</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">yarn</span> <span class="hljs-string">install</span> <span class="hljs-string">--frozen-lockfile</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">yarn</span> <span class="hljs-string">build</span>
</code></pre>
<p>If you’re using npm, add the following:</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v1</span>
  <span class="hljs-attr">with:</span>
    <span class="hljs-attr">node-version:</span> <span class="hljs-number">12</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">ci</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">build</span>
</code></pre>
<p>Between both of these sets of steps, what we’re doing is:</p>
<ul>
<li>Setting up node: this is so that we can use npm and node to install and run our scripts</li>
<li>Install Yarn (Yarn Only): if we’re using yarn, we install it as a global dependency so that we can use it</li>
<li>Install Dependencies: we install our dependencies and we use a specific command that makes sure we use the lock file available to avoid any unexpected package upgrades</li>
<li>Build: finally, we run our build command which will compile our Next.js project into the <code>out</code> directory!</li>
</ul>
<p>And now we can commit that file right to our <code>main</code> branch which will kick off a new run of our workflow that we can see in our Actions tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/github-action-run-workflow.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New workflow in GitHub Actions</em></p>
<p>To see that it works, we can navigate into that run, select our workflow, and see that all of our steps ran including building our project!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/github-action-successful-build.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Successful build logs for a GitHub Action workflow</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-static-website/commit/59e0a5158d6afbf54793d826d05455f5205c98fb">Follow along with the commit!</a></p>
<h2 id="heading-step-3-configuring-a-github-action-to-deploy-a-static-website-to-s3">Step 3: Configuring a GitHub Action to deploy a static website to S3</h2>
<p>Now that we’re building our project automatically, we want to automatically update our website in S3.</p>
<p>To do that, we’re going to use the GitHub Action <a target="_blank" href="https://github.com/aws-actions/configure-aws-credentials">aws-actions/configure-aws-credentials</a> and the AWS CLI.</p>
<p>The GitHub Action that we’re using will take in our AWS credentials and configuration and make it available to use throughout the lifecycle of the workflow.</p>
<p>As of now, the Ubuntu instance that GitHub Actions provides allows us to use the AWS CLI as it comes included. So we’ll be able to use the CLI commands right in our workflow.</p>
<p>Alternatively, we could use the <a target="_blank" href="https://github.com/jakejarvis/s3-sync-action">S3 Sync action</a>. But by using the AWS CLI, we gain more flexibility to customize our setup, we can use it for additional CLI commands, and it’s also generally nice to get familiar with the AWS CLI.</p>
<p>So to get started, let’s add the following snippet as additional steps in our workflow:</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">aws-actions/configure-aws-credentials@v1</span>
  <span class="hljs-attr">with:</span>
    <span class="hljs-attr">aws-access-key-id:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.AWS_ACCESS_KEY_ID</span> <span class="hljs-string">}}</span>
    <span class="hljs-attr">aws-secret-access-key:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.AWS_SECRET_ACCESS_KEY</span> <span class="hljs-string">}}</span>
    <span class="hljs-attr">aws-region:</span> <span class="hljs-string">us-east-1</span>
</code></pre>
<p>What the above will do is use the AWS credentials configuration action to set up our AWS Access Key, Secret Key, and region based on our settings.</p>
<p>The AWS Region can be customized to whatever region you typically use with your AWS account. I’m in the northeast United States, So I’ll keep <code>us-east-1</code>.</p>
<p>The Access Key and Secret Key are credentials that you’ll need to generate with your AWS account. The way our code is set up is that we’ll store those values inside of GitHub Secrets, which will prevent those keys from being leaked. When the action runs, Github changes those values to stars (<code>***</code>) so people can't access those keys.</p>
<p>So to set up those secrets, we first want to generate Access Keys in AWS.</p>
<p>Navigate to the AWS console. Under the user menu, select <strong>My Security Credentials</strong>, and then select <strong>Create access key</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/aws-console-create-access-key.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating an Access Key in AWS</em></p>
<p>This will provide you with two values: the <strong>Access key ID</strong> and the <strong>Secret access key</strong>. Save these values, as you won’t be able to access the Secret key ID again.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/aws-secret-access-keys.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Finding Secret and Access Key in AWS</em></p>
<p><em>Note: remember to NOT include the Access Key and Secret Key inside of your code. This could lead to someone compromising your AWS credentials.</em></p>
<p>Next, inside of the GitHub repo, navigate to Settings, Secrets, then select New secret.</p>
<p>Here we’ll want to add our AWS keys using the following secrets:</p>
<ul>
<li>AWS_ACCESS_KEY_ID: your AWS Access key ID</li>
<li>AWS_SECRET_ACCESS_KEY: your AWS Secret key</li>
</ul>
<p>And once saved you should have your two new secrets.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/github-secrets-access-keys.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating Secrets in GitHub</em></p>
<p>Now that we have our credentials configured, we should be ready to run the command to sync our project to S3.</p>
<p>Inside of the GitHub Action, add the following step:</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">aws</span> <span class="hljs-string">s3</span> <span class="hljs-string">sync</span> <span class="hljs-string">./out</span> <span class="hljs-string">s3://[bucket-name]</span>
</code></pre>
<p><em>Note: be sure to replace <code>[bucket-name]</code> with the name of your S3 Bucket.</em></p>
<p>This command will trigger a sync with our specified S3 bucket, using the contents of the <code>out</code> directory, which is where our project builds to.</p>
<p>And now, if we commit our changes, we can see that our action is automatically triggered once committed to the <code>main</code> branch, where we build our project and sync it to S3!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/github-action-sync-s3-bucket.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Successful AWS S3 sync in GitHub Action workflow</em></p>
<p><em>Note: Make sure that before setting up this action you’ve configured the S3 bucket to host a website (including unblocking permissions on S3 bucket) – otherwise this action may fail.</em></p>
<p>At this point, our project probably looks the same, as we didn’t make any changes to the code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nextjs-s3-website.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app on AWS S3</em></p>
<p>But if you make a code change, such as changing the title of the homepage inside of <code>pages/index.js</code> and commit that change:</p>
<pre><code class="lang-jsx">&lt;h1 className={styles.title}&gt;
  Colby<span class="hljs-string">'s &lt;a href="https://nextjs.org"&gt;Next.js!&lt;/a&gt; Site
&lt;/h1&gt;</span>
</code></pre>
<p>We can see that our change triggers the workflow to kick off:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/github-action-commit-workflow.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New GitHub Action workflow from code change</em></p>
<p>And once our workflow finishes, we can see that our content is now automatically updated on our website:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/updated-nextjs-site-title.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>AWS S3 hosted app with updated code changes</em></p>
<p>Follow along with the commits:</p>
<ul>
<li><a target="_blank" href="https://github.com/colbyfayock/my-static-website/commit/f891412b827aca4b06e9bf3de8e4e5b4c5704fc8">Adding AWS configuration and S3 sync command</a></li>
<li><a target="_blank" href="https://github.com/colbyfayock/my-static-website/commit/bb9b981416645e35c6d3442e02d6b61f2ba032d2">Title update to test workflow</a></li>
</ul>
<h2 id="heading-what-else-can-we-do">What else can we do?</h2>
<h3 id="heading-setting-up-cloudfront">Setting up CloudFront</h3>
<p>The goal of this post wasn’t to go through the entire process of configuring a website for AWS, but if you’re serving a website on S3,  you might want to also include CloudFront in front of it.</p>
<p>You can check out <a target="_blank" href="https://www.freecodecamp.org/news/how-to-host-and-deploy-a-static-website-or-jamstack-app-to-s3-and-cloudfront/">my other guide</a> here which walks you through setting up CloudFront as well as a step-by-step guide through creating the site in S3.</p>
<h3 id="heading-invaliding-cloudfront-cache">Invaliding CloudFront cache</h3>
<p>If your S3 website is behind CloudFront, chances are, you’ll want to make sure CloudFront isn’t caching the new changes.</p>
<p>With the AWS CLI, we can also trigger a cache invalidation with CloudFront to make sure it’s grabbing the latest changes.</p>
<p><a target="_blank" href="https://docs.aws.amazon.com/cli/latest/reference/cloudfront/create-invalidation.html">Check out the docs here</a> to learn more.</p>
<h3 id="heading-pull-request-deployments">Pull request deployments</h3>
<p>If you’re constantly working on website changes in a pull request, sometimes it can be easier to see the changes live.</p>
<p>You can set up a new workflow that only runs on pull requests, where the workflow can dynamically create a new bucket based on the branch or environment and add a comment to the pull request with that URL.</p>
<p>You might be able to find a GitHub Action that exists to manage the comments on the pull request for you or you can check out the <a target="_blank" href="https://docs.github.com/en/free-pro-team@latest/rest/reference/actions">GitHub Actions docs</a>.</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">🐦 Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">🎥 Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">💝 Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Chakra UI with Next.js and React ]]>
                </title>
                <description>
                    <![CDATA[ Building websites and applications is hard. There are a lot of things to consider to make sure our apps are usable and accessible including how our React components work.  How can we take advantage of the power of Chakra UI to build great web apps? ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-chakra-ui-with-next-js-and-react/</link>
                <guid isPermaLink="false">66b8e37147e3b55b9fb6ee47</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Libraries ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 21 Oct 2020 00:16:01 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/chakra.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Building websites and applications is hard. There are a lot of things to consider to make sure our apps are usable and accessible including how our React components work. </p>
<p>How can we take advantage of the power of Chakra UI to build great web apps?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-chakra-ui">What is Chakra UI?</a></li>
<li><a class="post-section-overview" href="#heading-what-makes-chakra-ui-so-great">What makes Chakra UI so great?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-step-0-creating-a-new-react-project-with-nextjs">Step 0: Creating a new React project with Next.js</a></li>
<li><a class="post-section-overview" href="#heading-step-1-installing-and-configuring-chakra-ui-in-nextjs">Step 1: Installing and configuring Chakra UI in Next.js</a></li>
<li><a class="post-section-overview" href="#heading-step-2-adding-chakra-ui-components-to-a-react-app">Step 2: Adding Chakra UI components to a React app</a></li>
<li><a class="post-section-overview" href="#heading-step-3-making-responsive-components-with-chakra-ui">Step 3: Making responsive components with Chakra UI</a></li>
<li><a class="post-section-overview" href="#heading-step-4-customizing-the-default-chakra-ui-theme">Step 4: Customizing the default Chakra UI theme</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/ubB5l-HVPgY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-chakra-ui">What is Chakra UI?</h2>
<p><a target="_blank" href="https://chakra-ui.com/">Chakra UI</a> is a component library for React that makes it easy to build the UI of an app or website.</p>
<p>Their goal is to provide a simple, modular, and accessible set of components to get up and running quickly.</p>
<h2 id="heading-what-makes-chakra-ui-so-great">What makes Chakra UI so great?</h2>
<p>To start, by default Chakra strives to make each component accessible. It’s a critical part of application development that’s often overlooked, and the Chakra maintainers have gone out of their way to ensure the components follow the <a target="_blank" href="https://www.w3.org/WAI/standards-guidelines/aria/">WAI-ARIA guidelines</a>.</p>
<p>Chakra also includes a simple API allowing developers to get productive. It allows people and teams to make inclusive apps without having to worry about building a bunch of components themselves.</p>
<p>For styling and customization, Chakra uses <a target="_blank" href="https://emotion.sh/">Emotion</a> under the hood to provide developers the ability to style their components right inside of their JavaScript with style props. It comes with a default theme, but allows the ability to easily override it with custom settings.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>To get a good idea of how Chakra works, we’re going to essentially rebuild the default Next.js template with Chakra UI components.</p>
<p>This will help us understand a few important concepts, such as how to use Chakra UI with Next.js, how to add custom styles with props, and how to customize the Chakra UI theme.</p>
<p>The concepts here can apply pretty much to any <a target="_blank" href="https://reactjs.org/">React</a> app, though the examples will be slightly specific to Next.js.</p>
<h2 id="heading-step-0-creating-a-new-react-project-with-nextjs">Step 0: Creating a new React project with Next.js</h2>
<p>To get started, we need a React app. We’re going to use Next.js as our framework which will give us the ability to easily spin up a new app.</p>
<p>Once inside the directory you want to create your project in, run:</p>
<pre><code>yarn create next-app my-chakra-app
# or
npx create-next-app my-chakra-app
</code></pre><p>Note: feel free to change <code>my-chakra-app</code> to whatever you want to name the project directory.</p>
<p>And once that’s finished, you can navigate into that directory and start the project with:</p>
<pre><code>yarn dev
# or
npm run dev
</code></pre><p>That should spin up your development server at <a target="_blank" href="http://localhost:3000">http://localhost:3000</a> and we should be ready to go!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nextjs-default-template.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Default Next.js template</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-chakra-app/commit/01f6ec8d961eb197fe3e8a32e498d07bf0be269b">Follow along with the commit!</a></p>
<h2 id="heading-step-1-installing-and-configuring-chakra-ui-in-nextjs">Step 1: Installing and configuring Chakra UI in Next.js</h2>
<p>Next, let’s install Chakra UI.</p>
<p>Inside of your project directory, run:</p>
<pre><code>yarn add @chakra-ui/core @emotion/core @emotion/styled emotion-theming
# or 
npm install @chakra-ui/core @emotion/core @emotion/styled emotion-theming
</code></pre><p>This will install Chakra UI and its dependencies, which includes Emotion, as it relies on it for the styling.</p>
<p>To get Chakra working inside of our app, we need to configure a Provider at the root of our application. This will allow all of Chakra’s components to talk to each other and use the configuration to maintain consistent styles.</p>
<p>Inside <code>pages/_app.js</code>, first let’s import our Provider at the top:</p>
<pre><code><span class="hljs-keyword">import</span> { ThemeProvider, theme } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/core'</span>;
</code></pre><p>Next, replace the return statement inside of the component with:</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeProvider</span> <span class="hljs-attr">theme</span>=<span class="hljs-string">{theme}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ThemeProvider</span>&gt;</span></span>
  )
}
</code></pre>
<p>As you’ll notice, we’re also passing a <code>theme</code> variable to our provider. We’re importing the Chakra UI default theme straight from Chakra and passing it in to our <code>ThemeProvider</code> so all of our components can get the default styles and configurations.</p>
<p>Finally, we want to add a component called <code>CSSReset</code> right as a direct child of our <code>ThemeProvider</code>.</p>
<p>First, add <code>CSSReset</code> as an import:</p>
<pre><code><span class="hljs-keyword">import</span> { ThemeProvider, theme, CSSReset } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/core'</span>;
</code></pre><p>Then add the component right inside <code>ThemeProvider</code>:</p>
<pre><code class="lang-jsx">&lt;ThemeProvider theme={theme}&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CSSReset</span> /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span></span>
&lt;/ThemeProvider&gt;
</code></pre>
<p>And now if we reload the page, we can see that things are looking a little bit different!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nextjs-chakra-ui-css-reset.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js with Chakra UI CSS Reset</em></p>
<p>The browser comes with a lot of default styles and by default, Chakra UI doesn’t override them. This includes styles like borders on a button element.</p>
<p>While we don’t necessarily need the CSS Reset here, we could override those things manually. This provides us with a foundation where we’ll know that Chakra UI is working as it’s intended to and we can start adding our components.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-chakra-app/commit/8538b3609cfac71b6ece60e36314edf9a189941b">Follow along with the commit!</a></p>
<h2 id="heading-step-2-adding-chakra-ui-components-to-a-react-app">Step 2: Adding Chakra UI components to a React app</h2>
<p>Now for the fun part. We’re going to use Chakra UI components to try to rebuild the Next.js default template. It’s not going to look 100% exactly like it, but it will carry the spirit and we can customize it as we’d like.</p>
<h3 id="heading-building-the-title-and-description">Building the Title and Description</h3>
<p>Starting from the top, let’s update our title and description.</p>
<p>At the top of the page, we need to import our <code>Heading</code> component:</p>
<pre><code><span class="hljs-keyword">import</span> { Heading, Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/core"</span>;
</code></pre><p>Then let’s replace the <code>&lt;h1&gt;</code> with:</p>
<pre><code class="lang-jsx">&lt;Heading <span class="hljs-keyword">as</span>=<span class="hljs-string">"h1"</span> size=<span class="hljs-string">"2xl"</span> mb=<span class="hljs-string">"2"</span>&gt;
  Welcome to Next.js!
&lt;/Heading&gt;
</code></pre>
<p>Here, we’re using the <a target="_blank" href="https://chakra-ui.com/heading">Heading</a> component which we then set “as” an <code>h1</code>. We can use any HTML heading element tag name, but since we’re replacing an h1, we want to use that.</p>
<p>We’re also setting a <code>size</code> attribute, which allows us to control how big out heading is, as well as <code>mb</code>, which stands for <code>margin-bottom</code>, allowing us to add some space below.</p>
<p>And we can already see our page is looking more like the default template.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/chakra-ui-heading-component.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Chakra UI Heading component</em></p>
<p>We also want to add back our link.</p>
<p>Add <code>Link</code> to our import statement at the top and then inside of our <code>&lt;Heading&gt;</code> component, replace the Next.js text with:</p>
<pre><code class="lang-jsx">&lt;Link color=<span class="hljs-string">"teal.500"</span> href=<span class="hljs-string">"https://nextjs.org"</span>&gt;Next.js!&lt;/Link&gt;
</code></pre>
<p>Chakra’s <a target="_blank" href="https://chakra-ui.com/link">Link</a> component creates a link as expected, but then allows us to use the style props to customize it. Here, we’re using the color variable <code>teal.500</code> that Chakra provides to change our link to Chakra’s colors.</p>
<p>And we can see that we have our Next.js link!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/chakra-ui-heading-with-link.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Chakra UI Heading with Link component</em></p>
<p>The last piece of the header is the description. For that, we want to use the Text component.</p>
<p>Add <code>Text</code>  and <code>Code</code> to the import statement and replace the description with:</p>
<pre><code class="lang-jsx">&lt;Text fontSize=<span class="hljs-string">"xl"</span> mt=<span class="hljs-string">"2"</span>&gt;
  Get started by editing &lt;Code&gt;pages/index.js&lt;/Code&gt;
&lt;/Text&gt;
</code></pre>
<p>We’re using the <a target="_blank" href="https://chakra-ui.com/text">Text</a> component to recreate a <code>&lt;p&gt;</code> tag and the <a target="_blank" href="https://chakra-ui.com/code">Code</a> component to create our <code>&lt;code&gt;</code> tag. Similar to our Heading component, we’re adding a <code>fontSize</code> to make the font bigger and <code>mt</code> which stands for <code>margin-top</code> to add some space above it.</p>
<p>And now we have our header!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/chakra-ui-text-with-code-component.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Chakra UI Text component with Code</em></p>
<h3 id="heading-replacing-info-cards-with-chakra-ui-components">Replacing info cards with Chakra UI components</h3>
<p>For each of our cards, we can use the same concepts as we did with the header to recreate each of our boxes.</p>
<p>To start, add an import for the <code>Flex</code> component and replace the tag <code>&lt;div className={styles.grid}&gt;</code> with:</p>
<pre><code class="lang-jsx">&lt;Flex flexWrap=<span class="hljs-string">"wrap"</span> alignItems=<span class="hljs-string">"center"</span> justifyContent=<span class="hljs-string">"center"</span> maxW=<span class="hljs-string">"800px"</span> mt=<span class="hljs-string">"10"</span>&gt;
  ...
&lt;/Flex&gt;
</code></pre>
<p>Make sure to leave all of the cards inside of the Flex component. The <a target="_blank" href="https://chakra-ui.com/flex">Flex</a> component will recreate our grid by adding Flexbox along with the same properties that were on the grid before.</p>
<p>At this point, it should exactly the same as it did before.</p>
<p>Next, add <code>Box</code> to the import statement and then replace the first card with:</p>
<pre><code class="lang-jsx">&lt;Box <span class="hljs-keyword">as</span>=<span class="hljs-string">"a"</span> href=<span class="hljs-string">"https://nextjs.org/docs"</span> p=<span class="hljs-string">"6"</span> m=<span class="hljs-string">"4"</span> borderWidth=<span class="hljs-string">"1px"</span> rounded=<span class="hljs-string">"lg"</span> flexBasis=<span class="hljs-string">"45%"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h3"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"lg"</span> <span class="hljs-attr">mb</span>=<span class="hljs-string">"2"</span>&gt;</span>Documentation <span class="hljs-symbol">&amp;rarr;</span><span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">fontSize</span>=<span class="hljs-string">"lg"</span>&gt;</span>Find in-depth information about Next.js features and API.<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span></span>
&lt;/Box&gt;
</code></pre>
<p>Similar to our Heading component, we’re setting our <a target="_blank" href="https://chakra-ui.com/box">Box</a> component “as” an <code>&lt;a&gt;</code> tag allowing it to serve as a link. We then configure our style props to replicate our cards.</p>
<p>Inside of that, we use the Heading and Text component to recreate the actual content of the cards.</p>
<p>And after only changing the first card, we can now see the changes:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/chakra-ui-box-component.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Chakra UI Box component</em></p>
<p>Now, we can go back and replace the other three cards with the same components to finish recreating our grid.</p>
<p>For fun, we can add a 5th card that links to Chakra UI:</p>
<pre><code class="lang-jsx">&lt;Box <span class="hljs-keyword">as</span>=<span class="hljs-string">"a"</span> href=<span class="hljs-string">"https://chakra-ui.com/"</span> p=<span class="hljs-string">"6"</span> m=<span class="hljs-string">"4"</span> borderWidth=<span class="hljs-string">"1px"</span> rounded=<span class="hljs-string">"lg"</span> flexBasis=<span class="hljs-string">"45%"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h3"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"lg"</span> <span class="hljs-attr">mb</span>=<span class="hljs-string">"2"</span>&gt;</span>Chakra UI <span class="hljs-symbol">&amp;rarr;</span><span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">fontSize</span>=<span class="hljs-string">"lg"</span>&gt;</span>Build accessible React apps &amp; websites with speed.<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span></span>
&lt;/Box&gt;
</code></pre>
<p>And with all of our changes, we can now see our recreated Next.js starting template!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/chakra-ui-nextjs-grid.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Chakra UI recreating Next.js grid</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-chakra-app/commit/a324f8cd1d4120027a7f4dbcb16f45980de5495a">Follow along with the commit!</a></p>
<h2 id="heading-step-3-making-responsive-components-with-chakra-ui">Step 3: Making responsive components with Chakra UI</h2>
<p>Part of what the default Next.js grid was able to provide was the ability for the cards to expand to full width once the size of the browser becomes small enough. This is particularly relevant at <code>600px</code>, which typically means someone’s on a mobile device.</p>
<p>If we look at our page on a mobile device, we can see that our cards aren’t filling up the entire width.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/chakra-ui-not-responsive.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Chakra UI default without responsive</em></p>
<p>Chakra allows us to <a target="_blank" href="https://chakra-ui.com/responsive-styles">set responsive styles</a> with its baked in sizing, allowing us to easily recreate our responsive grid cards.</p>
<p>To do this, instead of passing in a single value to our style props, we can pass in an array.</p>
<p>For instance, on each of our Box components, let’s update the <code>flexBasis</code> prop to:</p>
<pre><code class="lang-jsx">flexBasis={[<span class="hljs-string">'auto'</span>, <span class="hljs-string">'45%'</span>]}
</code></pre>
<p>Here, according to Chakra’s <a target="_blank" href="https://chakra-ui.com/responsive-styles">default responsive breakpoints</a> , we’re saying that by default, we want our <code>flexBasis</code> to be set as <code>auto</code>. But for anything <code>480px</code> and larger, again which is Chakra’s default first breakpoint, we set it to <code>45%</code>.</p>
<p>Chakra considers its responsive styling to be mobile first, which is why you see the <code>480px</code> act as a minimum size, not a maximum size.</p>
<p>And with that change, we can now see that on a large device, we still have our grid.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/chakra-ui-large-device.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Chakra UI components on large device</em></p>
<p>But now on mobile, our cards take up the entire width!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/chakra-ui-small-device.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Chakra UI components on small device</em></p>
<p>Using the array pattern works for all of the breakpoints, so if you wanted more control over your styles, Chakra lets you do that.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-chakra-app/commit/c08e80b60395aa738eaa8f8eb411ca7004ffac9d">Follow along with the commit!</a></p>
<h2 id="heading-step-4-customizing-the-default-chakra-ui-theme">Step 4: Customizing the default Chakra UI theme</h2>
<p>While Chakra provides a pretty great default theme, we also have the ability to customize it to our liking to match our brand or personal taste.</p>
<p>For instance, while the teal that we used for our Heading link is great and uses Chakra’s styles, what if I wanted to customize all links to use the purple that I <a target="_blank" href="https://colbyfayock.com/">use on my website</a>?</p>
<p>To start, Chakra comes with a default purple, so we can update our link to use that purple:</p>
<pre><code class="lang-jsx">Welcome to &lt;Link color=<span class="hljs-string">"purple.500"</span> href=<span class="hljs-string">"https://nextjs.org"</span>&gt;Next.js!&lt;/Link&gt;
</code></pre>
<p>And we see our change.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nextjs-purple-header.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Making Next.js header link purple with color style prop</em></p>
<p>That looks great, but let’s update it to the exact purple I use.</p>
<p>Inside of <code>pages/_app.js</code>, we’re going to create a new object at the top of the page, where we spread the default theme creating a new theme object. We’ll also replace the <code>theme</code> prop with our new object:</p>
<pre><code><span class="hljs-keyword">const</span> customTheme = {
  ...theme
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ThemeProvider</span> <span class="hljs-attr">theme</span>=<span class="hljs-string">{customTheme}</span>&gt;</span></span>
</code></pre><p>If we save and reload the page, it will look exactly the same.</p>
<p>Next, we want to update the colors, so in our custom theme object, let’s add the colors property, where we can then set our custom purple:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> customTheme = {
  ...theme,
  <span class="hljs-attr">colors</span>: {
    ...theme.colors,
    <span class="hljs-attr">purple</span>: <span class="hljs-string">'#692ba8'</span>
  }
}
</code></pre>
<p>Note: you’ll see here that we’re also spreading <code>theme.colors</code>. If we don’t, we’ll be replacing the colors object with only the purple value, meaning we won’t have any other colors.</p>
<p>But if we reload the page, our link isn’t purple anymore!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nextjs-link-no-color.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js link with no color</em></p>
<p>Chakra typically uses ranges of colors which allows us to use different shades of each of the colors. In our Link component, we’re specifying <code>purple.500</code> which we didn’t set to exist.</p>
<p>So to fix that, we can use a tool like <a target="_blank" href="https://smart-swatch.netlify.app/#692ba8">Smart Swatch</a> to get all of our color values that we need and set those in our custom theme object:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> customTheme = {
  ...theme,
  <span class="hljs-attr">colors</span>: {
    ...theme.colors,
    <span class="hljs-attr">purple</span>: {
      <span class="hljs-number">50</span>: <span class="hljs-string">'#f5e9ff'</span>,
      <span class="hljs-number">100</span>: <span class="hljs-string">'#dac1f3'</span>,
      <span class="hljs-number">200</span>: <span class="hljs-string">'#c098e7'</span>,
      <span class="hljs-number">300</span>: <span class="hljs-string">'#a571dc'</span>,
      <span class="hljs-number">400</span>: <span class="hljs-string">'#8c48d0'</span>,
      <span class="hljs-number">500</span>: <span class="hljs-string">'#722fb7'</span>,
      <span class="hljs-number">600</span>: <span class="hljs-string">'#59238f'</span>,
      <span class="hljs-number">700</span>: <span class="hljs-string">'#3f1968'</span>,
      <span class="hljs-number">800</span>: <span class="hljs-string">'#260f40'</span>,
      <span class="hljs-number">900</span>: <span class="hljs-string">'#10031a'</span>,
    }
  }
}
</code></pre>
<p>Tip: Smart Swatch actually lets you copy those values as a JavaScript object, making it easier to paste into our theme!</p>
<p>And now if we reload the page, we can see our purple!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nextjs-custom-purple.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js with custom purple</em></p>
<p>While we used a range value here, we can also specify color variables without a range.</p>
<p>Say I wanted to leave the default Chakra purple “as is” but provide a way for me to reference my purple.</p>
<p>To do that, I could remove those purple values and add a new custom variable:</p>
<pre><code><span class="hljs-keyword">const</span> customTheme = {
  ...theme,
  <span class="hljs-attr">colors</span>: {
    ...theme.colors,
    <span class="hljs-attr">spacejelly</span>: <span class="hljs-string">'#692ba8'</span>
  }
}
</code></pre><p>Then update my Link to use that color:</p>
<pre><code class="lang-jsx">Welcome to &lt;Link color=<span class="hljs-string">"spacejelly"</span> href=<span class="hljs-string">"https://nextjs.org"</span>&gt;Next.js!&lt;/Link&gt;
</code></pre>
<p>And we can see that we’re now using our purple without overriding the original:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nextjs-spacejelly-purple.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js with custom color variable</em></p>
<p>We can apply this to most parts of the styles of Chakra, including Typography and setting custom Breakpoints. It’s another way to make our project custom to our own while still taking advantage of the power of Chakra!</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-chakra-app/commit/b9d707ce3324207c25c2348934ca0c506402bd2f">Follow along with the commit!</a></p>
<h2 id="heading-what-else-can-you-do-with-chakra-ui">What else can you do with Chakra UI?</h2>
<p>While we went through some simpler examples, it really opens the door to more complex style changes and controls that Chakra provides with its component APIs.</p>
<p>There are also a whole lot of awesome components that you can use to transform your website or application and make development fast and easy!</p>
<p>They even <a target="_blank" href="https://chakra-ui.com/recipes">provide recipes</a> that have some examples of how you can combine the components resulting in powerful functionality. This includes a responsive header and even adding animations with Framer Motion.</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">? Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">? Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Commit Hooks to Git with Husky to Automate Code Tasks ]]>
                </title>
                <description>
                    <![CDATA[ There are a lot of tools to automate our code tasks. We can check for syntax issues with ESLint and format our code with Prettier.  But not everyone on the team will remember to run those commands every time they commit. How can we use Husky to add G... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-commit-hooks-to-git-with-husky-to-automate-code-tasks/</link>
                <guid isPermaLink="false">66b8e335684cb75ad7f76d18</guid>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Prettier ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 14 Oct 2020 15:58:01 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/husky.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>There are a lot of tools to automate our code tasks. We can check for syntax issues with ESLint and format our code with Prettier. </p>
<p>But not everyone on the team will remember to run those commands every time they commit. How can we use Husky to add Git hooks to run them for us?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-git-hooks">What are Git Hooks?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-husky">What is Husky?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#step-0-setting-up-a-new-project">Step 0: Setting up a new project</a></li>
<li><a class="post-section-overview" href="#step-1-installing-husky-to-a-project">Step 1: Installing Husky to a project</a></li>
<li><a class="post-section-overview" href="#step-2-configuring-husky-to-run-git-hooks">Step 2: Configuring Husky to run Git hooks</a></li>
<li><a class="post-section-overview" href="#step-3-using-husky-to-format-code-with-prettier">Step 3: Using Husky to format code with Prettier</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/tuzys2b1J70" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-are-git-hooks">What are Git Hooks?</h2>
<p><a target="_blank" href="https://git-scm.com/docs/githooks">Git hooks</a> are scripts that you can set up to <a target="_blank" href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">run at certain events</a> in the Git lifecycle. These events include different stages of a commit, like before a commit (pre-commit) and after a commit (post-commit).</p>
<p>These are useful in that they allow developers to run custom code tasks or even enforce standards by automating other scripts to run those tasks.</p>
<h2 id="heading-what-is-husky">What is Husky?</h2>
<p><a target="_blank" href="https://github.com/typicode/husky">Husky</a> is a tool that allows us to easily wrangle Git hooks and run the scripts we want at those stages.</p>
<p>It works by including an object right within our <code>package.json</code> file that configures Husky to run the scripts we specify. After that, Husky handles managing at which point in the Git lifecycle our scripts will run.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’re going to set up a simple project that we can use to test out Git hooks.</p>
<p>While you should be able to follow along with any project that you’re working with, I’m going to use <a target="_blank" href="https://nextjs.org/">Next.js</a> as the starting point for this project, simply for the fact that we can run a single command to get a project started.</p>
<p>One consideration about following along with this project, though, is that we’ll use <a target="_blank" href="https://prettier.io/">Prettier</a> as an example of what you can do with Git hooks. </p>
<p>Prettier is a tool that will automatically format our code for us, which if you’re not expecting that to happen, can cause a lot of stress. Following along with me using the Next.js project will allow you to test this out without making any unintentional changes.</p>
<p>As for testing the Git hooks, we’ll start by adding a simple command line statement to see Husky work. But we’ll also test out adding Prettier, which will automatically format our code for us.</p>
<p>Finally, at the time of writing this, Husky released an <a target="_blank" href="https://typicode.github.io/husky/#/">v5 Alpha</a> version of their Git hook solution. Given it’s still just an Alpha version, we’re going to move forward with <a target="_blank" href="https://github.com/typicode/husky/tree/v4.3.0">v4</a>, which allows us to easily install Husky with npm.</p>
<h2 id="heading-step-0-how-to-set-up-a-new-project">Step 0: How to set up a new project</h2>
<p>As I mentioned, you can really follow the same steps here with any project that’s managed with a <code>package.json</code> file. </p>
<p>Next.js is absolutely overkill for this walkthrough, but the goal is to minimize the steps for getting set up to actually work with Husky.</p>
<p>To get started with Next.js, navigate to the directory you want to start your project in and run the following:</p>
<pre><code>yarn create next-app my-husky-project
# or
npx create-next-app my-husky-project
</code></pre><p><em>Note: feel free to replace <code>my-husky-project</code> to whatever you’d like to name your directory.</em></p>
<p>This will create a new folder, create a new Next.js project, and install all the dependencies.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/create-next-app.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once it’s done, navigate to that new folder, and we should be ready to go!</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-husky-project/commit/9e0b39c8f34c2755e074a32ef9de8d4047b68f67">Follow along with the commit</a>.</p>
<h2 id="heading-step-1-how-to-install-husky-to-a-project">Step 1: How to install Husky to a project</h2>
<p>To install Husky, we can use yarn or npm.</p>
<pre><code>yarn add husky
# or
npm install husky
</code></pre><p><em>Note: if installing Husky at this point installs v5, that means v5 has been officially released. Please see the <a target="_blank" href="https://typicode.github.io/husky/#/">updated Husky documentation</a> or you can install the latest v4 version by specifying husky@4.3.0 (or whatever the latest version is) when installing.</em></p>
<p>Once the package is finished installing, we should be ready to go with Husky.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-husky-project/commit/720728cd595d41c9197640bd4c48e9133bd7d956">Follow along with the commit</a>.</p>
<h2 id="heading-step-2-how-to-configure-husky-to-run-git-hooks">Step 2: How to configure Husky to run Git hooks</h2>
<p>Next, we’re going to set up Husky so we can use it for our Git hooks.</p>
<p>Inside of our <code>package.json</code> file, create a new property called <code>husky</code> with an empty object.</p>
<pre><code class="lang-json"><span class="hljs-string">"husky"</span>: {},
</code></pre>
<p>You can add this really wherever you want in the <code>package.json</code> file, but I’m going to add it right below the <code>scripts</code>  property so I can more easily manage them together.</p>
<p>Inside of that, we want to add another property called <code>hooks</code> that also specifies an empty object:</p>
<pre><code class="lang-json"><span class="hljs-string">"husky"</span>: {
  <span class="hljs-attr">"hooks"</span>: {}
},
</code></pre>
<p>This is where we’re going to add our Git hooks. Husky supports pretty much <a target="_blank" href="https://git-scm.com/docs/githooks">all Git hooks defined by Git</a>, so we can be as flexible we would like within our Git event flow.</p>
<p>To test this out, I created <a target="_blank" href="https://github.com/colbyfayock/my-husky-project/tree/main+test">a new branch</a> where I literally added every Git hook from that page including a script that simply writes to the terminal <code>[Husky] event name</code>.</p>
<p><em>Note: don’t feel like you need to do this unless you’re curious. The goal is to be able to show you with my example how it works.</em></p>
<pre><code>“husky”: {
  “hooks”: {
    “applypatch-msg”: “echo \”[Husky] applypatch-msg\””,
    “pre-applypatch”: “echo \”[Husky] pre-applypatch\””,
    “post-applypatch”: “echo \”[Husky] post-applypatch\””,
    “pre-commit”: “echo \”[Husky] pre-commit\””,
</code></pre><p>What this will do is tell Husky that at every single stage where we’re permitted to hook into Git, tell us!</p>
<p>When I commit that change, we can immediately see that Husky fires off some of our scripts.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/husky-commit-hooks.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>These are all of the events that Git allows us to hook into that happen during the commit process.</p>
<p>And similarly, if I push those changes out to Github, I can see that the push process runs the <code>pre-push</code> hook!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/husky-push-hooks.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You may never use most of the hooks that Husky and Git provide (we only saw a few between those two commands). </p>
<p>But it’s awesome to be able to see how powerful this can be, whether it’s running code that formats our code, prevents secret access keys from being committed, or really anything else that can help automate important tasks to your workflow.</p>
<p>We can now see that we can configure Husky by specifying the configuration and the hooks right in our <code>package.json</code>.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-husky-project/commit/108583a7e96564baf0fac994eafa6cf98d65d03e">Follow along with the commit</a>.</p>
<p><em>Note: If you want to check out my branch that includes every Git hook to test with, <a target="_blank" href="https://github.com/colbyfayock/my-husky-project/tree/main+test">you can find it on Github</a>.</em></p>
<h2 id="heading-step-3-how-to-use-husky-to-format-code-with-prettier">Step 3: How to use Husky to format code with Prettier</h2>
<p>Finally, for a real-world use case, we’re going to test out using Prettier to automatically format our code.</p>
<p>Prettier is an opinionated code formatting tool that allows you to easily clean up your code to make it look like a single person wrote it.</p>
<p>Why are tools like Prettier important? When working through code, especially with a team, it’s important to maintain consistency so everyone knows what to expect. It will help prevent arguing over a semi-colon in a code review, but it will also help catch syntax errors and prevent bugs.</p>
<p><em>Warning: running Prettier will automatically format all of your code. While we’re going to test this out before committing the changes, once you apply this as a Git Hook, it will automate this process.</em></p>
<p>To get started with Prettier, let’s install it with our package manager:</p>
<pre><code>yarn add prettier -D
# or
npm install prettier --save-dev
</code></pre><p><em>Note: we’re installing Prettier as a <code>devDependency</code> as our application doesn’t need this to run.</em></p>
<p>Next, we can add a new script in our <code>package.json</code> that will make it easier to run Prettier to test this out.</p>
<p>Inside the <code>scripts</code> property, add:</p>
<pre><code class="lang-json"><span class="hljs-string">"lint"</span>: <span class="hljs-string">"prettier --check ."</span>
</code></pre>
<p>For this first test, we’re going to run it as a “check” which will allow us to see which files would change.</p>
<p>Run the following:</p>
<pre><code>yarn lint
# or 
npm run lint
</code></pre><p>And once we do, we can see that Prettier is telling us that would change the files listed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/prettier-check.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>At this point, our code will remain unchanged. But if we want to run Prettier for real to make those changes, we can first add an additional script:</p>
<pre><code class="lang-json"><span class="hljs-string">"format"</span>: <span class="hljs-string">"prettier --write ."</span>
</code></pre>
<p>And if we run that script, it will update all of those files to format the code to Prettier’s specification.</p>
<p><em>Warning: just another note, running Prettier to write the changes will make changes in your files. These are all code-style changes that shouldn’t impact how the code runs, but how the code looks. Before running format, you should save any changes by committing with Git so that you can easily revert the changes if you’re not happy with them.</em></p>
<p>You can now run the script with:</p>
<pre><code>yarn format
</code></pre><p>And we can see that Prettier updated our files!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/prettier-write.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now the part that’s relevant to this walkthrough: we can add this as a Git hook. This way, when someone tries to commit code, Prettier is run before the code is saved. This means that we’ll always keep code consistent with Prettier’s formatting style.</p>
<p>Inside our Husky hooks configuration, let’s add:</p>
<pre><code class="lang-json"><span class="hljs-string">"husky"</span>: {
  <span class="hljs-attr">"hooks"</span>: {
    <span class="hljs-attr">"pre-commit"</span>: <span class="hljs-string">"prettier --write . &amp;&amp; git add -A ."</span>
  }
},
</code></pre>
<p>If you notice in our pre-commit hook, we’re also adding <code>git add -A .</code>. </p>
<p>When Husky runs, it simply runs the script provided. When running our Prettier command, we’re only formatting the code, but we never save those changes as part of the process. So we use <code>git add</code> to store all of those changes and include them in the commit.</p>
<p>To test this out, I reverted the changes to all of the files that were formatted before. If you’re following along with the same project, you can run:</p>
<pre><code>git checkout pages
</code></pre><p>Which will reset all of the changes in <code>pages</code> to the last commit.</p>
<p>Now, let’s try to add all of our files with Git and commit the changes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/git-commit-husky-precommit-prettier.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And once we run our commit command, we can see that the Husky pre-commit hook kicks in already and formats our code!</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-husky-project/commit/315112d062a791f20eda11f9c608c5fa794ba73e">Follow along with the commit</a>.</p>
<h2 id="heading-what-can-i-do-next">What can I do next?</h2>
<h3 id="heading-use-lint-staged-to-only-run-formatting-on-changed-files">Use lint-staged to only run formatting on changed files</h3>
<p>We’re using Prettier right in our pre-commit hook and specifying <code>.</code> which means it’s going to run on all files every time.</p>
<p>We can use a tool called <a target="_blank" href="https://github.com/okonet/lint-staged">lint-staged</a>, which allows us to still run our Git hooks with Husky, but it will only run on files that are staged.</p>
<p>For instance, if we wanted to do this with Husky and Prettier, our configuration might look like:</p>
<pre><code><span class="hljs-string">"husky"</span>: {
  <span class="hljs-string">"hooks"</span>: {
    <span class="hljs-string">"pre-commit"</span>: <span class="hljs-string">"lint-staged"</span>
  }
},
<span class="hljs-string">"lint-staged"</span>: {
  <span class="hljs-string">"*"</span>: <span class="hljs-string">"prettier --write"</span>
},
</code></pre><p>As part of how lint-staged runs, it will attach the changed files to the end of our Prettier statement automatically for us.</p>
<p>You’ll also notice we didn't include <code>git add</code>. lint-staged will also add any changes to Git for us automatically.</p>
<h3 id="heading-set-up-a-prettier-config-to-customize-formatting-rules">Set up a Prettier config to customize formatting rules</h3>
<p>Prettier is very opinionated. There are some things I personally don’t prefer and you might feel the same.</p>
<p>Luckily, Prettier allows you to set up a configuration file that can override some of those files to make your code just the way you and your team want it.</p>
<h3 id="heading-tell-prettier-to-ignore-files-with-prettierignore">Tell Prettier to ignore files with .prettierignore</h3>
<p>You also probably don’t want Prettier running on “all the things” (maybe you do).</p>
<p>Prettier allows you to set up a <code>.prettierignore</code>  file right inside of the root of the project next to <code>package.json</code>, similar to <code>.gitignore</code>, that allows you to tell Prettier what files it should not run on.</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">? Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">? Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Drag and Drop in React with React Beautiful DnD ]]>
                </title>
                <description>
                    <![CDATA[ Drag and Drop is a common interaction technique added to allow people to intuitively move things around on a page. This could be reordering a list or even putting together a puzzle.  How can we add that interaction when building a React app with Reac... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-drag-and-drop-in-react-with-react-beautiful-dnd/</link>
                <guid isPermaLink="false">66b8e33a684cb75ad7f76d1a</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ user experience ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ux design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Mon, 05 Oct 2020 16:38:22 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/drag-and-drop-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Drag and Drop is a common interaction technique added to allow people to intuitively move things around on a page. This could be reordering a list or even putting together a puzzle. </p>
<p>How can we add that interaction when building a React app with React Beautiful DnD?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-drag-and-drop">What is Drag and Drop?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-react-beautiful-dnd">What is React Beautiful DnD?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-step-0-creating-a-new-reactjs-app">Step 0: Creating a new React.js app</a></li>
<li><a class="post-section-overview" href="#heading-step-1-installing-react-beautiful-dnd">Step 1: Installing React Beautiful DnD</a></li>
<li><a class="post-section-overview" href="#heading-step-2-making-a-list-draggable-and-droppable-with-react-beautiful-dnd">Step 2: Making a list draggable and droppable with React Beautiful DnD</a></li>
<li><a class="post-section-overview" href="#heading-step-3-saving-list-order-after-reordering-items-with-react-beautiful-dnd">Step 3: Saving list order after reordering items with React Beautiful DnD</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/aYZRRyukuIw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-drag-and-drop">What is Drag and Drop?</h2>
<p>Drag and drop is pretty much what it sounds like — it’s an interaction allowing someone to click and drag an item, then drop it somewhere else, often having a side effect within the app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/react-beautiful-dnd-board.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Moving items on a board</em></p>
<p>This effect is pretty common in applications like to-do lists or project management dashboard, where you need to prioritize and create an order for how things should be done.</p>
<p>While drag and drop can have some advanced use cases, we’ll stick to basic list functionality for our walkthrough.</p>
<h2 id="heading-what-is-react-beautiful-dnd">What is React Beautiful DnD?</h2>
<p>React Beautiful DnD is an accessible drag and drop library from Atlassian. If you don’t know of Atlassian, they’re the team behind Jira. If you’re not familiar with Jira, it’s probably the biggest Agile tool on the internet right now.</p>
<p>The team’s goals were to provide drag and drop capabilities with accessibility in mind, in addition to keeping it night and performant with a powerful API.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’re going to start off with a simple list and add the ability to drag and drop.</p>
<p>In this walkthrough, we won’t spend time building the list itself. The list that we’ll be using uses a standard unordered list (<code>&lt;ul&gt;</code>) and list items (<code>&lt;li&gt;</code>) to create a list with a little bit of CSS to make it look like cards.</p>
<p>We’ll be focusing on adding the ability to drag and drop to rearrange the list using React Beautiful DnD.</p>
<h2 id="heading-step-0-creating-a-new-reactjs-app">Step 0: Creating a new React.js app</h2>
<p>To get started, we want a simple app that includes a list of items. This can be an existing project or a brand new project using your favorite framework like <a target="_blank" href="https://create-react-app.dev/">Create React App</a>.</p>
<p>I started with a new app using Create React app and I added a simple list of <a target="_blank" href="https://www.tbs.com/shows/final-space">Final Space</a> characters.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/list-of-final-space-characters-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Final Space characters list</em></p>
<p>If you want to start from the same place, you can clone my demo repository at that branch and start right along with me.</p>
<p>This command will clone <a target="_blank" href="https://github.com/colbyfayock/my-final-space-characters/tree/part-0-starting-point">the specific branch</a> to get started:</p>
<pre><code>git clone --single-branch --branch part<span class="hljs-number">-0</span>-starting-point git@github.com:colbyfayock/my-final-space-characters.git
</code></pre><p>Otherwise, you can clone <a target="_blank" href="https://github.com/colbyfayock/my-final-space-characters">the repository</a> as normal and check out the branch <code>part-0-starting-point</code>.</p>
<p>If you want to follow along with just the code, I first created an array of objects:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> finalSpaceCharacters = [
  {
    <span class="hljs-attr">id</span>: <span class="hljs-string">'gary'</span>,
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Gary Goodspeed'</span>,
    <span class="hljs-attr">thumb</span>: <span class="hljs-string">'/images/gary.png'</span>
  },
  ...
</code></pre>
<p>And then I loop through them to create my list:</p>
<pre><code>&lt;ul className=<span class="hljs-string">"characters"</span>&gt;
  {finalSpaceCharacters.map(<span class="hljs-function">(<span class="hljs-params">{id, name, thumb}</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{id}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"characters-thumb"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{thumb}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">name</span>} <span class="hljs-attr">Thumb</span>`} /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
          { name }
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
    );
  })}
&lt;/ul&gt;
</code></pre><p><a target="_blank" href="https://github.com/colbyfayock/my-final-space-characters/commit/8bfa61c32c1bdace7515a93a14427108056f3814">Follow along with the commit!</a></p>
<h2 id="heading-step-1-installing-react-beautiful-dnd">Step 1: Installing React Beautiful DnD</h2>
<p>First step is to install the library via npm.</p>
<p>Inside of your project, run the following:</p>
<pre><code>yarn add react-beautiful-dnd
# or
npm install react-beautiful-dnd --save
</code></pre><p>This will add the library to our project and we’ll be ready to use it in our app.</p>
<h2 id="heading-step-2-making-a-list-draggable-and-droppable-with-react-beautiful-dnd">Step 2: Making a list draggable and droppable with React Beautiful DnD</h2>
<p>With our library installed, we can give our list the ability to drag and drop.</p>
<h3 id="heading-adding-drag-and-drop-context-to-our-app">Adding Drag and Drop context to our app</h3>
<p>At the top of the file, import <code>DragDropContext</code> from the library with:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { DragDropContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-beautiful-dnd'</span>;
</code></pre>
<p><a target="_blank" href="https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/drag-drop-context.md">DragDropContext</a> is going to give our app the ability to use the library. It works similarly to React’s Context API, where the library can now have access to the component tree.</p>
<p><em>Note: If you plan on adding drag and drop to more than one list, you need to make sure that your DragDropContext wraps all of those items, like at the root of your application. You can not nest DragDropContext.</em></p>
<p>We’ll want to wrap our list with DragDropContext:</p>
<pre><code class="lang-jsx">&lt;DragDropContext&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"characters"</span>&gt;</span>
  ...
<span class="hljs-tag">&lt;/<span class="hljs-name">DragDropContext</span>&gt;</span></span>
</code></pre>
<p>At this point, nothing will have changed with the app and it should still load as it did before.</p>
<h3 id="heading-making-our-list-a-droppable-area">Making our list a Droppable area</h3>
<p>Next, we want to create a Droppable area, meaning, this will allow us to provide a specific area where our items can be moved around inside.</p>
<p>First, add <code>Droppable</code> to our import at the top of the file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { DragDropContext, Droppable } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-beautiful-dnd'</span>;
</code></pre>
<p>For our purpose, we want our entire unordered list (<code>&lt;ul&gt;</code>) to be our drop zone, so we’ll again want to wrap it with this component:</p>
<pre><code class="lang-jsx">&lt;DragDropContext&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Droppable</span> <span class="hljs-attr">droppableId</span>=<span class="hljs-string">"characters"</span>&gt;</span>
    {(provided) =&gt; (
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"characters"</span>&gt;</span>
        ...
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    )}
  <span class="hljs-tag">&lt;/<span class="hljs-name">Droppable</span>&gt;</span></span>
&lt;/DragDropContext&gt;
</code></pre>
<p>You’ll notice we wrapped it a bit differently this time though. First, we set a <code>droppableId</code> on our <code>&lt;Droppable&gt;</code> component. This allows the library to keep track of this specific instance between interactions.</p>
<p>We’re also creating a function immediately inside of that component that passes in the <code>provided</code> argument.</p>
<p>Note: This function can pass in two arguments including a <code>snapshot</code> argument, but we won’t be using it in this example.</p>
<p>The <a target="_blank" href="https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/droppable.md#1-provided-droppableprovided">provided</a> argument include information and references to code that the library needs to work properly.</p>
<p>To use it, on our list element, let’s add:</p>
<pre><code class="lang-jsx">&lt;ul className=<span class="hljs-string">"characters"</span> {...provided.droppableProps} ref={provided.innerRef}&gt;
</code></pre>
<p>This is going to create a reference (<code>provided.innerRef</code>) for the library to access the list element’s HTML element.  It also applies props to the element (<code>provided.droppableProps</code>) that allows the library to keep track of movements and positioning.</p>
<p>Again, at this point, there won’t be any noticeable functionality.</p>
<h3 id="heading-making-our-items-draggable">Making our items Draggable</h3>
<p>Now for the fun part!</p>
<p>The final piece of making our list elements draggable and droppable is wrapping each list item with a component similar to what we just did with the entire list.</p>
<p>We’ll be using the <a target="_blank" href="https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/draggable.md">Draggable</a> component, which again, similar to the Droppable component, will include a function where we’ll pass through props to our list item components.</p>
<p>First, we need to import Draggable along with the rest of the components.</p>
<pre><code><span class="hljs-keyword">import</span> { DragDropContext, Droppable, Draggable } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-beautiful-dnd'</span>;
</code></pre><p>Next, inside of our loop, let’s wrap the returning list item with the <code>&lt;Draggable /&gt;</code> component and it’s top level function.</p>
<pre><code class="lang-jsx">{finalSpaceCharacters.map(<span class="hljs-function">(<span class="hljs-params">{id, name, thumb}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Draggable</span>&gt;</span>
      {(provided) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{id}</span>&gt;</span>
          ...
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">Draggable</span>&gt;</span></span>
</code></pre>
<p>Because we now have a new top level component in our loop, let’s move the <code>key</code> prop from the list element to Draggable:</p>
<pre><code class="lang-jsx">{finalSpaceCharacters.map(<span class="hljs-function">(<span class="hljs-params">{id, name, thumb}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;Draggable key={id}&gt;
      {(provided) =&gt; (
        &lt;li&gt;
</code></pre>
<p>We also need to set two addition props on <code>&lt;Draggable&gt;</code>, a <code>draggableId</code> and an <code>index</code>.</p>
<p>We’ll want to add <code>index</code> as an argument into our <code>map</code> function and then include those props on our component:</p>
<pre><code class="lang-jsx">{finalSpaceCharacters.map(<span class="hljs-function">(<span class="hljs-params">{id, name, thumb}, index</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Draggable</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{id}</span> <span class="hljs-attr">draggableId</span>=<span class="hljs-string">{id}</span> <span class="hljs-attr">index</span>=<span class="hljs-string">{index}</span>&gt;</span></span>
</code></pre>
<p>Finally, we need to set some props on the list element itself.</p>
<p>On our list element, add this <code>ref</code> and spread additional props from the <code>provided</code> argument:</p>
<pre><code class="lang-jsx">&lt;Draggable key={id} draggableId={id} index={index}&gt;
  {<span class="hljs-function">(<span class="hljs-params">provided</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{provided.innerRef}</span> {<span class="hljs-attr">...provided.draggableProps</span>} {<span class="hljs-attr">...provided.dragHandleProps</span>}&gt;</span></span>
</code></pre>
<p>Now, if we refresh our page, and hover over our list items, we can now drag them around!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/drag-items-revert-state-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Dragging items on a list</em></p>
<p>However, you’ll notice that when you start moving an item around, the bottom of the page appears to be a little messed up. There’s some overflow issues with our list items and our footer.</p>
<p>You’ll also notice that in the developer console, React Beautiful DnD is giving us a warning message that we’re missing something called a placeholder.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/react-beautiful-dnd-warning-placeholder.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Console warning - placeholder could not be found</em></p>
<h3 id="heading-adding-a-placeholder-from-react-beautiful-dnd">Adding a placeholder from React Beautiful DnD</h3>
<p>Part of React Beautiful DnD’s requirements is that we additionally include a placeholder item.</p>
<p>This is something that they provide out of the box, but this is used to fill up the space that the item we’re dragging previously took.</p>
<p>To add that, we want to include <code>provided.placeholder</code> at the bottom of our Droppable top level list component, in our case at the bottom of the <code>&lt;ul&gt;</code>:</p>
<pre><code class="lang-jsx">&lt;Droppable droppableId=<span class="hljs-string">"characters"</span>&gt;
  {<span class="hljs-function">(<span class="hljs-params">provided</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"characters"</span> {<span class="hljs-attr">...provided.droppableProps</span>} <span class="hljs-attr">ref</span>=<span class="hljs-string">{provided.innerRef}</span>&gt;</span>
      ...
      {provided.placeholder}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
  )}
&lt;/Droppable&gt;
</code></pre>
<p>And if we start dragging things around in our browser, we can see that our page flow doesn’t have issues and the content stays where it should!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/drag-items-revert-fixed-spacing.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Dragging items with fixed spacing</em></p>
<p>The last issue though, is when you move something around, it doesn’t stay, so how can we save the order of our items?</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-final-space-characters/commit/5ec5ee6c3e7de5b67a8fd46fdfbf157312bc8c00">Follow along with the commit!</a></p>
<h2 id="heading-step-3-saving-list-order-after-reordering-items-with-react-beautiful-dnd">Step 3: Saving list order after reordering items with React Beautiful DnD</h2>
<p>When we move our items, they stay where they land for a split second. But after React Beautiful DnD finishes doing its work, our component tree will rerender.</p>
<p>When the components rerender, our items go back to the same place that they were before, because we never saved that outside of DnD’s memory.</p>
<p>To resolve this, <code>DragDropContext</code> takes in an <code>onDragEnd</code> prop that will allow us to fire a function after dragging has complete. That function passes in arguments that includes the new order of our items so that we can update our state for the next render cycle.</p>
<h3 id="heading-saving-our-list-items-in-state">Saving our list items in state</h3>
<p>First, let’s store our items in state so that we’ll have something to update between cycles.</p>
<p>At the top of the file, add <code>useState</code> to the React import:</p>
<pre><code><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</code></pre><p>Then, we’re going to create our state using our default list of items.</p>
<p>Add the following to the top of our App component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [characters, updateCharacters] = useState(finalSpaceCharacters);
</code></pre>
<p>Because we’ll be updating our new <code>characters</code> state to provide our list items and their order, we’ll now want to replace the array we’re mapping through to our new state:</p>
<pre><code class="lang-jsx">&lt;ul className=<span class="hljs-string">"characters"</span> {...provided.droppableProps} ref={provided.innerRef}&gt;
  {characters(<span class="hljs-function">(<span class="hljs-params">{id, name, thumb}, index</span>) =&gt;</span> {
</code></pre>
<p>And if we save and refresh our page, nothing should change!</p>
<h3 id="heading-updating-state-when-dragging-items">Updating state when dragging items</h3>
<p>Now that we have our state, we can update that state any time our list items are dragged.</p>
<p>The <code>DragDropContext</code> component that we added to our page takes in a prop <code>onDragEnd</code>. Like it sounds, that will fire a function whenever someone stops dragging an item in the list.</p>
<p>Let’s add a function <code>handleOnDragEnd</code> as our prop:</p>
<pre><code>&lt;DragDropContext onDragEnd={handleOnDragEnd}&gt;
</code></pre><p>Next, we need that function to actually exist.</p>
<p>We can define a function under our state:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleOnDragEnd</span>(<span class="hljs-params">result</span>) </span>{
}
</code></pre>
<p>Our function takes an argument called <code>result</code>.</p>
<p>If we add <code>console.log(result)</code> to the function and move an item in our list, we can see that it includes details about what should be the updated state after our move action.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/react-beautiful-dnd-ondragend-result.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Dragged item result</em></p>
<p>Particularly, we want to use the <code>index</code> value in both the <code>destination</code> and <code>source</code> properties, which tell us the index of the item being moved and what the new index of that item should be in the array of items.</p>
<p>So using that, let’s add the following to our function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> items = <span class="hljs-built_in">Array</span>.from(characters);
<span class="hljs-keyword">const</span> [reorderedItem] = items.splice(result.source.index, <span class="hljs-number">1</span>);
items.splice(result.destination.index, <span class="hljs-number">0</span>, reorderedItem);

updateCharacters(items);
</code></pre>
<p>Here’s what we’re doing:</p>
<ul>
<li>We create a new copy of our <code>characters</code> array</li>
<li>We use the <code>source.index</code> value to find our item from our new array and remove it using the <code>splice</code> method</li>
<li>That result is destructured, so we end up with a new object of <code>reorderedItem</code> that is our dragged item</li>
<li>We then use our <code>destination.inddex</code> to add that item back into the array, but at it’s new location, again using <code>splice</code></li>
<li>Finally, we update our <code>characters</code> state using the <code>updateCharacters</code> function</li>
</ul>
<p>And now after saving our function, we can move our characters around, and they save their location!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/drag-drop-save-state.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Drag item with saved state</em></p>
<h3 id="heading-preventing-errors-from-dragging-out-of-bounds">Preventing errors from dragging out of bounds</h3>
<p>One issue with our implementation, is if someone doesn’t drag the item exactly within our defined containers, we get an error.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/drag-out-of-container-error.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Error when dragging out of container</em></p>
<p>The issue is that when we drag it outside of the defined container, we don’t have a destination.</p>
<p>To avoid this, we can simply add a statement above the code that moves our item around that checks if the destination exists, and if it doesn’t, exits out of the function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleOnDragEnd</span>(<span class="hljs-params">result</span>) </span>{
  <span class="hljs-keyword">if</span> (!result.destination) <span class="hljs-keyword">return</span>;
</code></pre>
<p>And if we reload the page and try to drag our item out again, our item snaps back to the original location without an error!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/drag-out-of-container-snap-back.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Snap back when dragged out of container</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-final-space-characters/commit/ad4f4733a974a27f5a2cfc8e366c2390809b74ca">Follow along with the commit!</a></p>
<h2 id="heading-what-else-can-we-do-with-react-beautiful-dnd">What else can we do with React Beautiful DnD?</h2>
<h3 id="heading-custom-styles-when-dragging-and-dropping">Custom styles when dragging and dropping</h3>
<p>When moving items, DnD will provide a snapshot of the given state. With this information, we can apply custom styles so that when we’re moving our items, we can show an active state for the list, the item we’re moving, or both!</p>
<p><a target="_blank" href="https://react-beautiful-dnd.netlify.app/?path=/story/single-vertical-list--basic">https://react-beautiful-dnd.netlify.app/?path=/story/single-vertical-list--basic</a></p>
<h3 id="heading-dragging-between-different-lists">Dragging between different lists</h3>
<p>If you’ve used Trello before or a tool like it, you should be familiar with the concept of different columns that you can drag cards between so that you can prioritize and organize your tasks and ideas.</p>
<p>This library allows you to do the same thing, providing the ability to drag and drop items from one draggable area to another.</p>
<p><a target="_blank" href="https://react-beautiful-dnd.netlify.app/?path=/story/multiple-vertical-lists--stress-test">https://react-beautiful-dnd.netlify.app/?path=/story/multiple-vertical-lists--stress-test</a></p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">? Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">? Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use SVG Icons in React with React Icons and Font Awesome ]]>
                </title>
                <description>
                    <![CDATA[ Icons are a way to visually communicate concepts and meaning without the use of words. This could be for categorization, an action, or even a warning.  How can we add icons using SVG to our React apps to improve our visual communication? What is SVG... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-svg-icons-in-react-with-react-icons-and-font-awesome/</link>
                <guid isPermaLink="false">66b8e37a6a98b2a27ee1f34e</guid>
                
                    <category>
                        <![CDATA[ Icons ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SVG ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 24 Sep 2020 16:07:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/react-icons.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Icons are a way to visually communicate concepts and meaning without the use of words. This could be for categorization, an action, or even a warning. </p>
<p>How can we add icons using SVG to our React apps to improve our visual communication?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-svg">What is SVG?</a></li>
<li><a class="post-section-overview" href="#heading-what-makes-svg-great-for-the-web">What makes SVG great for the web?</a></li>
<li><a class="post-section-overview" href="#heading-part-0-creating-a-react-app">Part 0: Creating a React app</a></li>
<li><a class="post-section-overview" href="#heading-part-1-adding-svg-icons-with-react-icons">Part 1: Adding SVG icons with react-icons</a></li>
<li><a class="post-section-overview" href="#heading-part-2-manually-adding-svg-files-to-a-react-component">Part 2: Manually adding SVG files to a React component</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/OtcA2EAlldo" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-svg">What is SVG?</h2>
<p><a target="_blank" href="https://www.w3.org/Graphics/SVG/">SVG</a> stands for Scalable Vector Graphics. It’s a file format based on a markup language similar to XML that allows developers and designers to create vector-based images using path definitions.</p>
<h2 id="heading-what-makes-svg-great-for-the-web">What makes SVG great for the web?</h2>
<p>SVG was born for the web. It’s an open standard that was created by W3C to provide a better way to add images to the web. If you open an SVG file on your computer, you might be surprised to find that it’s all code!</p>
<p>This plays a part in the small file size. Typically when using SVG, you can take advantage of its smaller size compared to larger image files that might be required to deliver the same high resolution.</p>
<p>Additionally, since we’re defining SVG as paths, they can scale as large or as small as we want. This makes them extra flexible for web usage, especially when making experiences responsive.</p>
<h2 id="heading-what-are-we-going-to-create">What are we going to create?</h2>
<p>We’re first going to walk through using a package called <a target="_blank" href="https://react-icons.github.io/react-icons/">react-icons</a> that will allow us to easily import icons from popular icon sets like <a target="_blank" href="https://fontawesome.com/">Font Awesome</a> right into our app.</p>
<p>We’ll also take a look at how we can manually add SVG files right into our app by copying the code of an SVG file right into a new component.</p>
<h2 id="heading-part-0-creating-a-react-app">Part 0: Creating a React app</h2>
<p>For this walkthrough, you can use any React framework you’d like whether that’s <a target="_blank" href="https://create-react-app.dev/">Create React App</a> or <a target="_blank" href="https://nextjs.org/">Next.js</a>. You can even use an existing project.</p>
<p>Because we don’t need anything special to add our icons, I’m going to use create-react-app.</p>
<p>To get started with create-react-app, you can create a new project using the following command in your terminal:</p>
<pre><code>yarn create react-app [project-name]
# or
npx create-react-app [project-name]
</code></pre><p><em>Note: replace <code>[project-name]</code> with the name you want to use for your project. I’m going to use <code>my-svg-icons</code>.</em></p>
<p>Once you have your new app or your existing app, we should be ready to go!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/new-create-react-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Create React App</em></p>
<h2 id="heading-part-1-adding-svg-icons-with-react-icons">Part 1: Adding SVG icons with react-icons</h2>
<h3 id="heading-adding-react-icons-to-your-project">Adding react-icons to your project</h3>
<p>To get started with react-icons, we want to install it in our project.</p>
<p>Inside of your project, run the following command:</p>
<pre><code>yarn add react-icons
# or
npm install react-icons --save
</code></pre><p>Once it’s completed, we should be ready to use it in our project.</p>
<h3 id="heading-selecting-icons-for-a-project">Selecting icons for a project</h3>
<p>One of the cool things about react-icons is the extensive library they make available within the single package.</p>
<p>Not only do we have Font Awesome immediately available, we have <a target="_blank" href="https://primer.style/octicons">GitHub’s Octicons</a>, <a target="_blank" href="https://heroicons.com/">Heroicons</a>, <a target="_blank" href="https://google.github.io/material-design-icons/">Material Design Icons</a>, and <a target="_blank" href="https://react-icons.github.io/">a whole bunch more</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/react-icons-heroicons.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>react-icons Heroicons</em></p>
<p>When choosing icons, you pretty much have the ability to use any icon you want at any time. That said, I would recommend trying to keep a consistent look and feel with your icons.</p>
<p>If you primarily use Font Awesome for your website, it might look a bit strange and inconsistent if you were to start adding <a target="_blank" href="https://react-icons.github.io/icons?name=fc">Flat Color Icons</a> to the mix. You ultimately want to provide an experience that people will be able to easily identify the patterns that you create.</p>
<h3 id="heading-using-react-icons-in-your-project">Using react-icons in your project</h3>
<p>Once you’ve found the icons you want to use, we can now add them to our project.</p>
<p>react-icons’s website makes it easy for us to look up the name of the icon we want to use to import to our project.</p>
<p>If we wanted to use the Font Awesome rocket icon, we can navigate to Font Awesome in the sidebar, search the page for “rocket” (CMD+F or CTRL+F), and then click the icon which will copy its name to your clipboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/font-awesome-rocket.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Font Awesome rocket icon</em></p>
<p>We could also search for “rocket” in the search form at the top left of the page, which shows us the result “rocket” throughout all icon sets.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/react-icons-rocket.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Rocket icons in react-icons</em></p>
<p>Inside of our project, we can now import that icon. Similar to the instructions at the top of the react-icons page, we want to import that specific icon from the <code>react-icons/fa</code>, which refers to the Font Awesome module of react-icons.</p>
<p>Add the following to the top of the file you want to import the icon in. If using a new create-react-app project, you can add it to the top of <code>src/App.js</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { FaRocket } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-icons/fa'</span>;
</code></pre>
<p>To test this out, let’s replace the React logo with our icon.</p>
<p>Remove the <code>&lt;img</code> component and instead add:</p>
<pre><code class="lang-jsx">&lt;FaRocket /&gt;
</code></pre>
<p>And if we reload the page, we can see our rocket!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/create-react-app-rocket-icon.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Rocket icon in React app</em></p>
<p>Our rocket isn’t spinning like the React logo though, so let’s fix that.</p>
<p>Add the class <code>.App-logo</code> to the <code>FaRocket</code> component:</p>
<pre><code class="lang-jsx">&lt;FaRocket className=<span class="hljs-string">"App-logo"</span> /&gt;
</code></pre>
<p>And the rocket should now be spinning!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/create-react-app-rocket-spin.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Spinning rocket icon in React app</em></p>
<p>But it’s also a little small. If we look inside of <code>src/App.css</code>, we’re setting the height of <code>.App-logo</code> to <code>40vmin</code>. While that’s working, for our icon to fill the space, we need to also provide a width for it to fill.</p>
<p>Add the following to the <code>.App-logo</code> class to add a width:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">width</span>: 40<span class="hljs-selector-tag">vmin</span>;
</code></pre>
<p>And while it’s probably a little too big now, we’re at a more appropriate size and we have our icon!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/create-react-app-icon-rocket-spin-large.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Increased size of spinning rocket icon in React app</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-svg-icons/commit/036112c3e2ffc5f42a53c68e8025fe70a87e3b13">Follow along with the commit</a>.</p>
<h2 id="heading-part-2-manually-adding-svg-files-to-a-react-component">Part 2: Manually adding SVG files to a React component</h2>
<p>Sometimes you don’t want to add a new library just to get an icon. Sometimes it’s a custom icon that’s not available in a public library.</p>
<p>Luckily with React, we can create a new SVG component pretty easily that allows us to add our custom SVG icons anywhere we want.</p>
<p>First, let’s find an icon.</p>
<p>While all Heroicons are available inside react-icons, let’s use it as an example since it’s easy to find and copy some SVG code.</p>
<p>Go to heroicons.com and search for an icon that you’d like to use for this example. I’m going to use “globe”.</p>
<p>After finding the icon you want, hover over that icon, where you’ll see options to copy that icon as SVG or JSX, and copy it as JSX.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/heroicons-copy-svg.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Copy as JSX in Heroicons</em></p>
<p>With that icon copied, create a new file under <code>src</code> called <code>Globe.js</code>.</p>
<p>Inside of that file, we’re going to create a new component called Globe and paste in our SVG within that component.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> Globe = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"currentColor"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">stroke-linecap</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-linejoin</span>=<span class="hljs-string">"round"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"2"</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Globe;
</code></pre>
<p><em>Note: when copying normal SVG to a React component, it might not work "as is". Sometimes SVG files include CSS classes or element attributes that aren't valid with JSX.</em> </p>
<p><em>If you run into errors, try fixing the attributes and looking at the web console to see the warnings and errors React throws. Because we copied as JSX, we were able to make it work right away.</em></p>
<p>Now, go back to <code>src/App.js</code> and import our new component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Globe <span class="hljs-keyword">from</span> <span class="hljs-string">'./Globe'</span>;
</code></pre>
<p>Then we can replace our rocket icon with our new component:</p>
<pre><code class="lang-jsx">&lt;Globe /&gt;
</code></pre>
<p>And if we open up our browser, we can see our globe!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/create-react-app-globe-large.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Large globe icon in REact app</em></p>
<p>Though, it’s a little big.</p>
<p>We want to apply our <code>.App-logo</code> class to our Globe component, so we need to update that component to take a <code>className</code> prop.</p>
<p>Back at <code>src/Globe.js</code>, add a <code>className</code> prop argument:</p>
<pre><code><span class="hljs-keyword">const</span> Globe = <span class="hljs-function">(<span class="hljs-params">{ className }</span>) =&gt;</span> {
</code></pre><p>Then, add a new prop with that <code>className</code> to the <code>&lt;svg</code> component:</p>
<pre><code class="lang-jsx">&lt;svg className={className}
</code></pre>
<p>Now, we can update our Globe component in <code>src/App.js</code> to include that class:</p>
<pre><code class="lang-jsx">&lt;Globe className=<span class="hljs-string">"App-logo"</span> /&gt;
</code></pre>
<p>And if we reload the page, we can see our logo is back at the right size and it’s spinning again!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/create-react-app-globe-icon-spinning.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Spinning, normal size globe icon in React app</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-svg-icons/commit/87b00748fc9b38d80336ddb5f6f823388c2edead">Follow along with the commit</a>.</p>
<h2 id="heading-why-dont-we-include-it-as-an-img-file">Why don’t we include it as an img file?</h2>
<p>While we can include it as an image file just like React does in the default create-react-app code, we get a few benefits from adding our SVG files “inline”.</p>
<p>For one, when adding SVG inline, we can access the different paths with CSS properties. This gives us more flexibility for customizing it dynamically.</p>
<p>It’s also going to provide fewer HTTP requests. The browser will know how to load that SVG, so we don’t need to bother the browser to request that file to include in the page.</p>
<p>That said, it’s still a valid option for adding an SVG file to the page.</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">? Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">? Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Jamstack Site with Next.js and Vercel - Jamstack Handbook ]]>
                </title>
                <description>
                    <![CDATA[ The Jamstack architecture is a modern approach to an old idea: making fast, static websites, but making them dynamic with tools like JavaScript.  How can we leverage the web framework Next.js and hosting platform Vercel to build and deploy performant... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-jamstack-site-with-next-js-and-vercel-jamstack-handbook/</link>
                <guid isPermaLink="false">66b8e34589963e292346f67b</guid>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 17 Sep 2020 16:08:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/jamstack-handbook.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The Jamstack architecture is a modern approach to an old idea: making fast, static websites, but making them dynamic with tools like JavaScript. </p>
<p>How can we leverage the web framework Next.js and hosting platform Vercel to build and deploy performant and reliable web apps?</p>
<p><em>Note: This is a preview of my <a target="_blank" href="https://jamstackhandbook.com/">Jamstack Handbook</a>, a guide to everything you need to know about the Jamstack. It has 3 tutorials, including this one. <a target="_blank" href="https://jamstackhandbook.com/">Get your copy</a> and learn how to build fast, dynamic apps with JavaScript and the static web.</em></p>
<ul>
<li><a class="post-section-overview" href="#heading-what-will-we-build">What will we build?</a></li>
<li><a class="post-section-overview" href="#heading-step-1-getting-started-with-a-nextjs-react-app">Step 1: Getting started with a Next.JS React app</a></li>
<li><a class="post-section-overview" href="#heading-step-2-setting-up-the-project-with-git">Step 2: Setting up the project with Git</a></li>
<li><a class="post-section-overview" href="#heading-step-3-deploying-nextjs-with-vercel">Step 3: Deploying Next.js with Vercel</a></li>
<li><a class="post-section-overview" href="#heading-what-did-we-just-deploy">What did we just deploy?</a></li>
<li><a class="post-section-overview" href="#heading-understanding-modern-ci-cd-with-git">Understanding modern CI / CD with Git</a></li>
<li><a class="post-section-overview" href="#heading-make-a-change-and-watch-it-automatically-deploy">Make a change and watch it automatically deploy</a></li>
<li><a class="post-section-overview" href="#heading-what-did-we-learn">What did we learn?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9nV4pIrKmyE" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p><a target="_blank" href="https://nextjs.org/">Next.js</a> is a web framework that’s built and maintained by <a target="_blank" href="https://vercel.com/">Vercel</a>. Next.js makes it easy to spin up a new React application and provides a ton of features out of the box like server side rendering (SSR) and static site generation (SSG).</p>
<h2 id="heading-what-will-we-build">What will we build?</h2>
<p>Our project itself will be relatively simple. We’re going to use the default Next.js Starter as a way to easily bootstrap the project, learn how to configure Next.js to statically compile, and then deploy that project with our customizations to Vercel.</p>
<blockquote>
<p>A Starter is a template that allows developers to recreate that template from the command line. When installing the starter, the framework will set up the project and install all dependencies.</p>
</blockquote>
<h2 id="heading-step-1-getting-started-with-a-nextjs-react-app">Step 1: Getting started with a Next.JS React app</h2>
<p>To get started, we first want to navigate to the directory we want to create our project in.</p>
<p>We’ll use a Starter to create our project. To do this, we have two options for a package manager to use: yarn or npm. You can choose whichever you feel more comfortable with for the remainder of the walkthrough.</p>
<pre><code>yarn create next-app
# or
npx create-next-app
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/09/yarn-create-next-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new Next.js app</em></p>
<p>When running this command, Next.js will first ask you for a project name. Here we can use any name we want to identify the project. I’m going to use my-nextjs-app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-project-name.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Naming a Next.js project</em></p>
<p>Once installation is finished, we’re now ready to get started with Next.js.</p>
<p>Navigate in your terminal to the new directory where your project is located and run:</p>
<pre><code>yarn dev
# or
npm run dev
</code></pre><p>This will start your development server, which will make your new site available at <a target="_blank" href="http://localhost:3000">http://localhost:3000</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-dev-server.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Starting Next.js development server</em></p>
<p>If you open up your <a target="_blank" href="http://localhost:3000">http://localhost:3000</a> address, you should now see the Next.js default project!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-default-starter.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js app</em></p>
<h2 id="heading-step-2-setting-up-the-project-with-git">Step 2: Setting up the project with Git</h2>
<p>You'll want to set this next step up on your own. Create a new repository with your favorite Git provider that’s supported by Vercel.</p>
<p>At the time of writing this, <a target="_blank" href="https://vercel.com/docs/git-integrations">Vercel supports GitHub, Gitlab, and Bitbucket</a>.</p>
<p>If you’re choosing a provider for the first time, GitHub is a solid option and is easy to get started.</p>
<p>You’ll then want to add your project to that new repository and push the project up to Git.</p>
<blockquote>
<p>Need help? Check out “Adding an existing project to GitHub using the command line” <a target="_blank" href="https://docs.github.com/en/github/importing-your-projects-to-github/adding-an-existing-project-to-github-using-the-command-line">https://docs.github.com/en/github/importing-your-projects-to-github/adding-an-existing-project-to-github-using-the-command-line</a></p>
</blockquote>
<p>For the rest of this walkthrough, I’ll be referencing GitHub, but the instructions should be the same for any supported provider.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-app-github.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app on GitHub</em></p>
<h2 id="heading-step-3-deploying-nextjs-with-vercel">Step 3: Deploying Next.js with Vercel</h2>
<p>Once your project is set up with GitHub, navigate to vercel.com and log in.</p>
<p>If you don’t already have a Vercel account, you should create one now. I would recommend creating an account with your GitHub account as it will help you import your project.</p>
<p>Inside the Vercel dashboard, click <strong>Import Project</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-import-project.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Import project to Vercel</em></p>
<p>Next, under Import Git Repository, click <strong>Continue</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-import-git-repository.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Import Git repository to Vercel</em></p>
<p>Vercel will now ask for the repository URL. This will be the homepage for the repository you just created for your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-git-repo-url.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Add Git repo URL to Vercel</em></p>
<p>After you click Continue, Vercel has already detected that your project uses Next.js. This means that we don’t need to set up and custom configurations, and we can hit Deploy!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-deploy-nextjs.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Deploy Next.js project to Vercel</em></p>
<p>At this point, Vercel will get to work and start to build the new project and deploy it to their infrastructure.</p>
<p>Once it’s finished, it will congratulate you and give you a link to visit your site.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-new-site-deployed.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Vercel project successfully deployed</em></p>
<p>Click Visit and you’ll be directed to your project live on the internet:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-app-on-vercel.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app live</em></p>
<h2 id="heading-what-did-we-just-deploy">What did we just deploy?</h2>
<p>We just created a new React app with Next.js and deployed it to Vercel.</p>
<p>We’ll walk through each specific step:</p>
<ul>
<li><strong>Create Next App:</strong> We first created a new Next.js project on our computer. This provided us with a new React application complete with dependencies and code to get started with a basic website.</li>
<li><strong>Add Project to Git:</strong> We added our new Next.js project to a Git repository online that’s supported by Vercel. This allows us to easily interface with the project with other services like Vercel.</li>
<li><strong>Connect Git to Vercel:</strong> We imported our project from Git into Vercel. This allowed Vercel to interact with our code.</li>
<li><strong>Build &amp; Deploy with Vercel:</strong> Vercel downloaded our code, was able to recognize it was a Next.js project, built our project, and deployed the compiled output to its infrastructure and made it available on the web.</li>
</ul>
<p>If you were waiting for more steps to get your project out to the world, there are none! The entry point for publishing a new React project is now lower than it’s ever been and Next.js and Vercel are helping you get there.</p>
<h2 id="heading-understanding-modern-ci-cd-with-git">Understanding modern CI / CD with Git</h2>
<p>Another benefit of modern infrastructure providers like Vercel, is that when utilizing GitHub as a service connection, Vercel can watch for changes on our main branch.</p>
<p>Once Vercel recognizes that a change was made, it will download the latest code and re-run the same process as we did the first time (aside from any caching and optimization).</p>
<p>This means that any time we have new changes to our production branch, they’ll automatically be deployed. </p>
<h2 id="heading-make-a-change-and-watch-it-automatically-deploy">Make a change and watch it automatically deploy</h2>
<p>To test out the automatic deployments, let’s make a change to our project.</p>
<p>Inside our project, let’s make a change to some of the page content inside of <code>pages/index.js</code>. I’m going to change the title to “Colby’s Next.js Project”.</p>
<pre><code class="lang-jsx">&lt;h1 className={styles.title}&gt;
  Colby<span class="hljs-string">'s Next.js App
&lt;/h1&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/colbys-nextjs-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app with change</em></p>
<p>Next, commit this change to your main Git branch and push it up to GitHub.</p>
<p>If you wait a few seconds and navigate back to <a target="_blank" href="https://vercel.com">vercel.com</a>, find your project and click on the Deployments tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-deployments.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Vercel deployment when change detected</em></p>
<p>You’ll see that your project is now running or might have already finished if you weren’t quick enough. Now if you open your website link again, you’ll see the changes deployed!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/deployed-nextjs-app-vercel.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Deployed changed Next.js app to Vercel</em></p>
<h2 id="heading-what-did-we-learn">What did we learn?</h2>
<p>Next.js is a web framework that allows us to quickly and easily spin up a new React application. </p>
<p>This, along with other similar frameworks, can be useful to get immediately productive instead of spending time building the project framework ourselves.</p>
<p>Vercel is a hosting and deployment platform that allows us to integrate with our favorite supported Git provider. Once connected, Vercel will download our project, build our project, and deploy the output to the internet.</p>
<p>Modern infrastructure tools like Vercel will watch for changes on our Git repository and will build and deploy our project so that we’re always seeing the latest version.</p>
<h2 id="heading-learn-more-about-the-jamstack">Learn more about the Jamstack!</h2>
<p>You can learn more about the Jamstack, including 2 more in depth tutorials, with my Jamstack Handbook.</p>
<p>
    <a href="https://jamstackhandbook.com/">
        <img src="https://www.freecodecamp.org/news/content/images/2020/09/jamstack-handbook-social.jpg" alt="Jamstack Handbook: Building fast, dynamic apps with Javascript and the static web" width="600" height="400" loading="lazy">
        Order at jamstackhandbook.com
    </a>
</p>

<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">? Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">? Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Organize and Sync SVG Files with Iconset ]]>
                </title>
                <description>
                    <![CDATA[ SVG is an awesome way to bring vector images into a design and development workflow. But collecting and organizing SVG files on your computer can be challenging.  How can Iconset help take away the pain and get us more productive? What is SVG? What ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-organize-and-sync-svg-files-with-iconset/</link>
                <guid isPermaLink="false">66b8e3620a89d796f29a16f5</guid>
                
                    <category>
                        <![CDATA[ Icons ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SVG ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 08 Sep 2020 15:47:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/iconset.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>SVG is an awesome way to bring vector images into a design and development workflow. But collecting and organizing SVG files on your computer can be challenging. </p>
<p>How can Iconset help take away the pain and get us more productive?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-svg">What is SVG?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-iconset">What is Iconset?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-learn">What are we going to learn?</a></li>
<li><a class="post-section-overview" href="#heading-part-1-getting-started-with-iconset">Part 1: Getting started with Iconset</a></li>
<li><a class="post-section-overview" href="#heading-part-2-adding-icons-to-iconset">Part 2: Adding icons to Iconset</a></li>
<li><a class="post-section-overview" href="#heading-part-3-using-iconset-with-design-software-like-figma">Part 3: Using Iconset with design software like Figma</a></li>
<li><a class="post-section-overview" href="#part-4-using-iconset-in-development-like-react">Part 4: Using Iconset in development like with React</a></li>
<li><a class="post-section-overview" href="#heading-part-5-syncing-iconset-across-multiple-computers-with-dropbox">Part 5: Syncing Iconset across multiple computers with Dropbox</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/KXBf5l4rbL4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-svg">What is SVG?</h2>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/SVG">SVG</a> is a nearly 20 year old image file format. And while it’s been around for a while, it has only recently been gaining momentum in the development  community.</p>
<p>SVG is great for a number of reasons. First of all, it’s a vector format, meaning it scales as big or small as you want. </p>
<p>But it’s also flexible in that you can use SVG right in your development project with a typically small file size and infinite scale. You can even <a target="_blank" href="https://frontend.horse/issues/6/#slash">animate it</a>!</p>
<p>But trying to collect and organize a bunch of files can be challenging. What do you name them? Do you have a computer that can easily preview them? What about search?</p>
<h2 id="heading-what-is-iconset">What is Iconset?</h2>
<p><a target="_blank" href="https://iconset.io/">Iconset</a> is a free cross-platform tool that allows you to collect and manage all of your SVG files in one place.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-font-awesome.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Iconset library</em></p>
<p>Love to quickly move between <a target="_blank" href="https://fontawesome.com/">Font Awesome</a> and <a target="_blank" href="https://heroicons.com/">heroicons</a> but don’t want to keep switching libraries? You can use Iconset to make a quick search and drag it right into your project.</p>
<p>If you’re planning on using it for a <a target="_blank" href="https://reactjs.org/">React</a> project, you can even copy the file as JSX and dump it right into your project!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-copy-as.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Iconset "Copy As"</em></p>
<h2 id="heading-what-are-we-going-to-learn">What are we going to learn?</h2>
<p>We’re going to walk through a few different scenarios that'll show us how Iconset is useful. </p>
<p>We’re also going to walk through how you can easily manage Iconset between different computers or environments so you can have the same great library anywhere you work.</p>
<h2 id="heading-part-1-getting-started-with-iconset">Part 1: Getting started with Iconset</h2>
<p>To get started, you’ll need to first install Iconset locally. It should be a similar installation process as any other application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-no-icons.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Iconset with no icons</em></p>
<p>Once it’s ready and available locally, you should be able to open it up and see a UI with No Icons, which is expected, as it doesn’t come with any icons out of the box.</p>
<h2 id="heading-part-2-adding-icons-to-iconset">Part 2: Adding icons to Iconset</h2>
<p>Adding icons to Iconset is as easy as dragging in, but you have a few options during the process.</p>
<p>To get started, let’s download the free icon set <a target="_blank" href="https://heroicons.com/">heroicons</a>.</p>
<p>Download at: <a target="_blank" href="https://heroicons.com/">https://heroicons.com/</a>.</p>
<p>On the heroicons website, you should see a big Download all button, which will download a zip file including all of the files.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/download-heroicons.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Downloading heroicons</em></p>
<p>If you navigate to the optimized folder, you’ll see that there are two different versions: solid and outline.</p>
<p>Now to get these into Iconset, select each folder individually and drag it right into Iconset.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-drag-in-icons.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Dragging heroicons into Iconset</em></p>
<p>Once there, you have a few options.</p>
<ul>
<li><strong>Set:</strong> Since this is our first set, you’ll automatically be creating a new one. If you had existing sets, you could import into those sets.</li>
<li><strong>Set Name:</strong> Here we can name the set something that we’ll remember. For this, I recommend naming it “heroicons - Outline”.</li>
<li><strong>Import Options:</strong> these are optional settings, but I typically select the optimize and clean option to make sure any icons are immediately ready to get working with.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-heroicons.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Iconset with heroicons set</em></p>
<p>And once you click Import, it will do it’s thing, and you’ll now have your first set of icons in Iconset!</p>
<p>You can go ahead and do the same thing with the solid directory so then we’ll now have our two sets ready to go.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-heroicons-solid-outline.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Iconset with Outling and Solid sets of heroicons</em></p>
<p>At this point, you can use Iconset to search through your icons and see all of your files currently available in your collection.</p>
<h2 id="heading-part-3-using-iconset-with-design-software-like-figma">Part 3: Using Iconset with design software like Figma</h2>
<p>The great thing about Iconset is how easy it is to use it with design software like <a target="_blank" href="http://figma.com/">Figma</a>.</p>
<p>If I wanted to add an envelope icon to my website so people could contact me, I could search for the mail icon, and simply drag it onto my canvas:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-drag-icon-into-figma.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Dragging mail icon into Figma</em></p>
<p>I can then treat it like any other vector design element and immediately use it in my project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/svg-icon-in-figma.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>SVG Mail icon in Figma</em></p>
<h2 id="heading-part-4-using-iconset-in-development-like-with-react">Part 4: Using Iconset in development like with React</h2>
<p>Another cool thing is how easy it is to use in a project like React.</p>
<p>Out of the box, you get a few different ways you can copy the file and use it in development like copying it as JSX.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-starter-sass.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js Sass Starter</em></p>
<p>If I feel like my <a target="_blank" href="https://github.com/colbyfayock/next-sass-starter">Next.js Sass Starter</a> could use some icons on the page, I can right-click any icon I want and under Copy As select JSX I can paste it right into my project!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-copy-icon-as-jsx.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Copying icon from Iconset as JSX</em></p>
<p>And while it will need some styling once you drop it in just like any other image or icon, it’s immediately ready to go.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/svg-icon-nextjs-project.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Using icon JSX in Next.js React app</em></p>
<h2 id="heading-part-5-syncing-iconset-across-multiple-computers-with-dropbox">Part 5: Syncing Iconset across multiple computers with Dropbox</h2>
<p>With Iconset, you have the ability to switch between different libraries. But importantly, you can also set the location of your library.</p>
<p>When Iconset creates your library, it stores everything as files and a database on your computer.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-location.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Iconset library folder</em></p>
<p>And inside the Iconset UI, we can both Move and Switch the location we use.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-settings.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Iconset library settings</em></p>
<p>If this is your first time setting up Iconset, you can start by clicking Move and then selecting the location you want to sync it to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-move-location.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Moving Iconset library location</em></p>
<p>And once you click Move, it will move it to that directory, like a folder on Dropbox, and sync to the cloud like any other folder and file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-sync-to-dropbox.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Syncing Iconset library with Dropbox</em></p>
<p>Alternatively, if you already have a shared Iconset library or if you’re setting this up on a new computer, you can use the Switch option, and select that option right from Dropbox.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-switch-locations.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Switching Iconset location</em></p>
<p>And once you hit Switch, you’ll now load up your shared library and be ready to get productive.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/iconset-full-library.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Iconset with full library</em></p>
<h2 id="heading-what-else-can-you-do">What else can you do?</h2>
<h3 id="heading-publish-and-share-icon-sets">Publish and share icon sets</h3>
<p>Another cool feature is that you can export sets and share them. If you’ve spent a lot of time on a collection and want to share it with others, export it, publish it, and share it with the community!</p>
<h3 id="heading-more-organization">More organization</h3>
<p>Iconset also supports features like Folders and Favorites. This makes it even easier to group and collect the icons however it makes sense to you to keep you productive.</p>
<p>It also supports tagging, making it even easier to search.</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">? Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">? Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Contact Form with Netlify Forms and Next.js ]]>
                </title>
                <description>
                    <![CDATA[ If you want someone to be able to contact you or submit information on a website, an HTML form is a pretty standard way to achieve that.  But accepting form submissions usually requires an additional service or complex server-side code. How can we ta... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-contact-form-with-netlify-forms-and-nextjs/</link>
                <guid isPermaLink="false">66b8e34b0cedc1f2a4f70699</guid>
                
                    <category>
                        <![CDATA[ Netlify ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 26 Aug 2020 17:13:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/netlify-forms.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you want someone to be able to contact you or submit information on a website, an HTML form is a pretty standard way to achieve that. </p>
<p>But accepting form submissions usually requires an additional service or complex server-side code. How can we take advantage of Netlify to easily create new forms?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-netlify">What is Netlify?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-how-much-does-this-cost">How much does this cost?</a></li>
<li><a class="post-section-overview" href="#heading-part-1-creating-a-contact-form-with-html">Part 1: Creating a contact form with HTML</a></li>
<li><a class="post-section-overview" href="#heading-part-2-adding-a-custom-netlify-form-to-a-nextjs-react-app">Part 2: Adding a custom Netlify form to a Next.js React app</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/GLxgxnLTVLE" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-netlify">What is Netlify?</h2>
<p><a target="_blank" href="https://www.netlify.com/">Netlify</a> is a web platform that lets you easily deploy new web projects with easy to configure workflows. This includes deploying a static website, lambda functions, and like we’ll talk about here, custom forms.</p>
<p>Their form service works as part of the build and deployment pipeline. When we include a form with a specific attribute to our page, Netlify will recognize that form and configure it to work.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’re going to build a contact form that will allow people to send you a note through your website.</p>
<p>The form itself will be pretty simple. Like a standard contact form, we'll ask for someone's name, email address, and a message.</p>
<p>We’re going to build this out using plain HTML to demonstrate how it works and then build it with <a target="_blank" href="https://nextjs.org/">Next.js</a> for creating a form in a React app.</p>
<h2 id="heading-how-much-does-this-cost">How much does this cost?</h2>
<p>Netlify forms are free to get started. This free tier is limited to 100 form submissions per website per month, so if you stay under that, it will always be free.</p>
<p>That said, if you exceed 100 form submission on any particular site, the first tier is going to be $19+ at the time of writing this. You can check out the <a target="_blank" href="https://www.netlify.com/pricing/">latest pricing plans on Netlify’s website</a>.</p>
<h2 id="heading-part-1-creating-a-contact-form-with-html">Part 1: Creating a contact form with HTML</h2>
<p>To get started, we’re going to create a basic form with pure HTML. It’s a quick win to demonstrate how this works.</p>
<h3 id="heading-step-1-creating-an-html-form">Step 1: Creating an HTML form</h3>
<p>For our form, we can really use whatever we want. Contact forms can be as simple as an email address and a message field or it include a variety of options to help a business answer specific questions.</p>
<p>We’re going to start with something simple. We’ll create a form that asks for someone’s name, email address, and a message.</p>
<p>To get started, create a new HTML file in the root of your project. This HTML file should include the basic structure of an HTML document. Inside of the body, let’s add our new form:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"contact"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span> <span class="hljs-attr">data-netlify</span>=<span class="hljs-string">"true"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"name"</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"message"</span>&gt;</span>Message<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Send<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>In the snippet above, we’re:</p>
<ul>
<li>Creating a new form</li>
<li>The form has a name attribute, a method, and a <code>data-netlify</code> attribute set to <code>true</code></li>
<li>Creating 3 form fields with labels, each identified with a name attribute</li>
<li>Creating a button to submit the form</li>
</ul>
<p>The thing we want to take most notice of is the <code>data-netlify</code> attribute and the form <code>name</code>. When Netlify reads the site, it will see those fields and use those to turn your form into an actively working form.</p>
<p>I’m also going to add a little bit of CSS to make the labels look a little more consistent. You can optionally add this to the <code>&lt;head&gt;</code> of the document:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-family</span>: sans-serif;
  }
  <span class="hljs-selector-tag">label</span> {
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">margin-bottom</span>: .<span class="hljs-number">2em</span>;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>And at this point, we should have a basic form!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/basic-html-form-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Basic HTML form</em></p>
<p>You’ll now want to put this form on GitHub or your favorite Netlify-supported Git provider and we’ll be ready for the next step.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-html-netlify-form/commit/482a4e14b3c8e10bc9ae29c2f233c3312dd1b89a">Follow along with the commit!</a></p>
<h3 id="heading-step-2-configuring-a-new-form-with-netlify">Step 2: Configuring a new form with Netlify</h3>
<p>Once our form is pushed to our Git provider, we can now sync it up with Netlify.</p>
<p>First create an account or use an existing account with Netlify and click the <strong>New site from Git</strong> button.</p>
<p>Here, select whichever Git provider you used. I'm using <strong>GitHub</strong> in my example.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/netlify-connect-git-provider.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Connecting a Git provider in Netlify</em></p>
<p>Once selecting your Git provider, it will ask you to authorize access so that Netlify can find your Git repository.</p>
<p>After you successfully connect your account, you should now see a list of the repositories you provided access to. Find the repository you added your form to and select it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/connecting-git-repo-netlify.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Connecting a Git repository to Netlify</em></p>
<p>If you’re following along with me, our form is pure HTML, meaning, there should be no build steps or no special directory it gets published to. But feel free to tweak these settings if you did something different.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/configuring-build-steps-netlify.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Configuring the build steps in Netlify</em></p>
<p>Now, click <strong>Deploy site</strong> which will open up a new page in Netlify and in no time your site will be successfully deployed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/netlify-site-successfully-deployed.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Finally, click the URL at the top of the Netlify project dashboard that ends in netlify.app. Once it's loaded, you’ll see your form!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/html-form-netlify.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-3-viewing-form-submissions">Step 3: Viewing form submissions</h3>
<p>Now that we have our form, we ultimately want to see responses.</p>
<p>To get started, add some information to your form and click submit.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/testing-html-form.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Testing HTML form</em></p>
<p>Once you submit, you’ll notice you get taken to a Netlify page that says the form was successfully submitted.</p>
<p>You can now go back to your Netlify project dashboard and scroll down a little bit where you can now see a box with <strong>Recent form submissions</strong> as well as your new submission.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/netlify-form-submission.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Netlify Form submission</em></p>
<h2 id="heading-part-2-adding-a-custom-netlify-form-to-a-nextjs-react-app">Part 2: Adding a custom Netlify form to a Next.js React app</h2>
<p>If the form is going to live by itself and not be part of a bigger site, there are a lot of advantages to leaving your form as pure HTML. But often, we want our contact form to be part of our website or app.</p>
<p>Here we’ll walk through adding a form to a <a target="_blank" href="https://nextjs.org/">Next.js</a> app.</p>
<p><em>Note: our demo of using Next.js is a statically rendered app. If you’re loading your form client side, meaning the underlying HTML doesn’t include the form, check out the notes at the bottom of this page for more information on solutions.</em></p>
<h3 id="heading-step-0-creating-a-nextjs-app">Step 0: Creating a Next.js app</h3>
<p>To start off, we need an app. We’re going to use Next.js since we can pretty easily spin up a new app from scratch.</p>
<p>To do this, you can navigate to where you want to create the app and run:</p>
<pre><code>yarn create next-app [project-name]
# or
npx create-next-app [project-name]
</code></pre><p>I’m going to name my project <code>my-nextjs-netlify-form</code>.</p>
<p>Once Next.js finishes installing dependencies, it’ll give you instructions to navigate to your project directory and start your development server.</p>
<p>And after you run <code>yarn dev</code> or <code>npm run dev</code>, you should be ready to go with your Next.js app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/new-nextjs-app-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js app</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-nextjs-netlify-form/commit/6f9fb6966b6c112a3ec934e305f2dd115e9d424e">Follow along with the commit!</a></p>
<h3 id="heading-step-1-adding-an-html-form-to-a-nextjs-app">Step 1: Adding an HTML form to a Next.js app</h3>
<p>Our Step 1 is going to look very similar to Part 1.</p>
<p>Inside of <code>pages/index.js</code>, we want to find our grid wrapper and we’ll use that to add our form.</p>
<p>Find <code>&lt;div className={styles.grid}&gt;</code> and replace the entire block with the following:</p>
<pre><code class="lang-jsx">&lt;div className={styles.grid}&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.card}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"contact"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span> <span class="hljs-attr">data-netlify</span>=<span class="hljs-string">"true"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"name"</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"message"</span>&gt;</span>Message<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Send<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>Here’s what we’re doing:</p>
<ul>
<li>We’re taking advantage of the existing grid from Next.js</li>
<li>We’re also taking advantage of the existing card that we’ll include our form in</li>
<li>Inside of the card, we’re pasting in the exact same HTML form as Part 1</li>
</ul>
<p>If we reload the page, we can now see our form inside of a card, like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/form-nextjs-react-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding a form to a Next.js app</em></p>
<p>Now before we move on, we want to do 2 things.</p>
<p>First, because we’re creating this form in a JavaScript app, <a target="_blank" href="https://www.netlify.com/blog/2017/07/20/how-to-integrate-netlifys-form-handling-in-a-react-app/#form-handling-with-static-site-generators">Netlify recommends</a> that we add a hidden input with our form name.</p>
<p>Inside of our form, add the following input at the top of the form element:</p>
<pre><code>&lt;input type=<span class="hljs-string">"hidden"</span> name=<span class="hljs-string">"form-name"</span> value=<span class="hljs-string">"contact"</span> /&gt;
</code></pre><p>Make sure the value of that input is the same as your form’s name.</p>
<p>Second, because the card that we’re reusing is intended for a list of links, Next.js includes some hover effects. This makes the form confusing to use, so let’s remove those</p>
<p>Remove the following from <code>styles/Home.module.css</code>:</p>
<pre><code>.card:hover,
.card:focus,
.card:active {
  <span class="hljs-attr">color</span>: #<span class="hljs-number">0070</span>f3;
  border-color: #<span class="hljs-number">0070</span>f3;
}
</code></pre><p>For an extra bonus step, I’m going to update my page title to “Contact Me” and remove the description. Feel free to make this whatever you want.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/nextjs-contact-form-title.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Updating the form title</em></p>
<p>And once you’re ready, similar to before, add this as a new repository to GitHub or your favorite Git provider.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-nextjs-netlify-form/commit/b9cac11411c6c71ee648c8631c35740735c599b7">Follow along with the commit!</a></p>
<h3 id="heading-step-2-setting-up-and-deploying-your-nextjs-app-to-netlify">Step 2: Setting up and deploying your Next.js app to Netlify</h3>
<p>Deploying our app to Netlify will look pretty similar, but before we get there, we need to set up our Next.js app to be able to export on build.</p>
<p>In our Next.js app, inside of the <code>package.json</code> file, we want to update the <code>build</code> script to:</p>
<pre><code class="lang-json"><span class="hljs-string">"build"</span>: <span class="hljs-string">"next build &amp;&amp; next export"</span>,
</code></pre>
<p>Now when you run the <code>build</code> script, it will compile the app to static HTML, CSS, and JS inside of the <code>out</code> directory. This will let us deploy it to Netlify. You can even try it locally on your machine if you want.</p>
<p>With that change, commit that and push it out to your Git provider.</p>
<p>Next, deploying the app will mostly look similar to Part 1. The only difference is because we have a Next.js app, we need to add our build steps.</p>
<p>To get started, we’ll want to connect our Git provider just like in Part 1.</p>
<p>Once we get to the Deploy Settings page, we want to configure our Build command and our Publish directory.</p>
<p>Our <strong>Build command</strong> will be <code>yarn build</code> or <code>npm run build</code> depending on what package manager you used and the <strong>Publish directory</strong> will be <code>out</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/netlify-deploy-settings-nextjs-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Deploy settings for a static Next.js app</em></p>
<p>After that, click <strong>Deploy site</strong>, and it will kick off just like before.</p>
<p>Once it’s finished deploying, we’ll now be ready to open the app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/successfully-deployed-nextjs-app-netlify.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Successfully deployed Next.js app on Netlify</em></p>
<p>And once we open up our app we can test our form by filling it out and hitting submit.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/testing-nextjs-contact-form.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Similar to before, we’ll land on a Netlify success page. But if we go back and look inside of our Netlify dashboard, we’ll now see our submission!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/successful-nextjs-form-submission-netlify-form.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Succesful Next.js form submission on Netlify</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-nextjs-netlify-form/commit/3a4516a706af550a37372a9aa2bbaf54b9d7d691">Follow along with the commit!</a></p>
<h3 id="heading-bonus-keep-people-on-your-website-with-a-success-message">Bonus: Keep people on your website with a success message</h3>
<p>Another cool feature with Netlify forms is that it allows you to set up your form to keep people on your website by configuring the form right on the page.</p>
<p>You have a lot of options here, whether it’s redirecting someone to a new page or configuring messaging on the page they submitted from.</p>
<p>For this demo, we’re going to set up a URL parameter that we can detect to show a success message if we see that parameter.</p>
<p>To do this, on your HTML form, add the following attribute:</p>
<pre><code>action=<span class="hljs-string">"/?success=true"</span>
</code></pre><p>This will tell Netlify we want to stay on the homepage (since we only have one page) but apply the URL parameter so we can detect it in our app.</p>
<p>Next, we can use the <code>useState</code> and <code>useEffect</code> hooks to see this parameter and update the page.</p>
<p>At the top of the file, let’s import these hooks:</p>
<pre><code><span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</code></pre><p>Inside of our Home component at the top, let’s add our state:</p>
<pre><code><span class="hljs-keyword">const</span> [success, setSuccess] = useState(<span class="hljs-literal">false</span>);
</code></pre><p>And to detect the URL parameter, we can use the <code>useEffect</code> hook:</p>
<pre><code class="lang-jsx">useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">if</span> ( <span class="hljs-built_in">window</span>.location.search.includes(<span class="hljs-string">'success=true'</span>) ) {
    setSuccess(<span class="hljs-literal">true</span>);
  }
}, []);
</code></pre>
<p><em>Note: this is a simple way of achieving this result for the demo. If you have a more complicated app, you might want to name the parameter something more logical and properly parse the URL parameters for the value.</em></p>
<p>What this is doing, is when the component renders, it will fire this <code>useEffect</code> hook, checking the parameters in the URL, and looking for <code>success=true</code>. If it finds it, it will update our <code>success</code> state variable to <code>true</code>!</p>
<p>Next, under our page title (<code>&lt;h1&gt;</code>), let’s add the following snippet:</p>
<pre><code class="lang-jsx">{success &amp;&amp; (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> '<span class="hljs-attr">green</span>'}}&gt;</span>
    Successfully submitted form!
  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
</code></pre>
<p>Here we’re looking to see if <code>success</code> is true, and if it its, we include a line of text that says the form was successfully submitted.</p>
<p>While you can’t submit your form locally, you can test this out by visiting your app running locally with the <code>?success=true</code> URL parameter like:</p>
<pre><code>http:<span class="hljs-comment">//localhost:3000/?success=true</span>
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/08/testing-success-message-locally.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Testing success message locally</em></p>
<p>Finally, you can push these changes out to your Git provider and Netlify will automatically rebuild your site.</p>
<p>And once it’s finished, you can submit your form like before and see the success message.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/netlify-success-redirect.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Successful form redirect on Netlify</em></p>
<p>And see that our form is still submitting!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/form-submission-success-netlify.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Successful form submission on Netlify</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-nextjs-netlify-form/commit/25378cd6b17ad6bb48dc7281220ab48eba74f478">Follow along with the commit!</a></p>
<h2 id="heading-netlify-forms-and-client-side-code">Netlify forms and client-side code</h2>
<p>One thing to take note of with Netlify’s solution is this only works this “simply” for static HTML pages. </p>
<p>If your page uses JavaScript to manage the content of that page, such as not adding a form until after the page loads, you’ll need to check out Netlify’s documentation on how you can make this work <a target="_blank" href="https://docs.netlify.com/forms/setup/#javascript-forms">with an additional form attribute</a>.</p>
<p>Netlify also gives an example on how you can <a target="_blank" href="https://docs.netlify.com/forms/setup/#submit-forms-via-ajax">submit your form dynamically with JavaScript</a> so you can create a custom experience in your app.</p>
<h2 id="heading-what-else-can-you-do">What else can you do?</h2>
<h3 id="heading-setting-up-advanced-workflows-with-other-tools">Setting up advanced workflows with other tools</h3>
<p>Netlify lets you integrate with other tools to allow you to wrangle your form submissions. Notably, <a target="_blank" href="https://zapier.com/apps/netlify/integrations">Netlify works with Zapier</a>, meaning you can accept incoming submissions and do whatever you want with them.</p>
<p><a target="_blank" href="https://docs.netlify.com/forms/notifications/">https://docs.netlify.com/forms/notifications/</a></p>
<h3 id="heading-preventing-spam-with-recaptcha">Preventing spam with reCAPTCHA</h3>
<p>Spam is also a real thing. You don’t want your inbox flooded with spam, so you can take advantage of Netlify’s built-in Honeypot field or they walk you through how to add reCAPTCHA 2.</p>
<p><a target="_blank" href="https://docs.netlify.com/forms/spam-filters/">https://docs.netlify.com/forms/spam-filters/</a></p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">? Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">? Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Next.js Starter to Easily Bootstrap a New React App ]]>
                </title>
                <description>
                    <![CDATA[ Getting started with a new React app is easier than ever with frameworks like Next.js. But those frameworks don’t always include all of the tools you want to use.  How can we use Starters to become super productive when starting a new project with ou... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-nextjs-starter-to-easily-bootstrap-a-new-react-app/</link>
                <guid isPermaLink="false">66b8e35389963e292346f67d</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Sass ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 18 Aug 2020 15:33:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/nextjs-starter.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Getting started with a new React app is easier than ever with frameworks like Next.js. But those frameworks don’t always include all of the tools you want to use. </p>
<p>How can we use Starters to become super productive when starting a new project with our favorite tools?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-nextjs">What is Next.js?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-a-starter">What is a Starter?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-adding-sass-to-a-nextjs-starter">Adding Sass to a Next.js Starter</a></li>
<li><a class="post-section-overview" href="#heading-setting-up-nextjs-starter-documentation-for-easy-setup">Setting up Next.js Starter documentation for easy setup</a></li>
<li><a class="post-section-overview" href="#heading-some-other-things-to-consider">Some other things to consider</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/oFGs_x7kxZg" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-nextjs">What is Next.js?</h2>
<p><a target="_blank" href="https://nextjs.org/">Next.js</a> is an application framework from <a target="_blank" href="https://vercel.com/">Vercel</a> that allows you to very quickly bootstrap a new <a target="_blank" href="http://reactjs.org/">React</a> application.</p>
<p>Some basic features include creating <a target="_blank" href="https://nextjs.org/docs/basic-features/pages">pages</a> and <a target="_blank" href="https://nextjs.org/docs/basic-features/data-fetching">data fetching</a>, and they allow you to generate a static site or use server side rendering to dynamically load your app. </p>
<p>On top of that, you can take advantage of its advanced features like <a target="_blank" href="https://nextjs.org/docs/routing/introduction">Routing</a> or creating an <a target="_blank" href="https://nextjs.org/docs/api-routes/introduction">API</a> right next to your UI.</p>
<h2 id="heading-what-is-a-starter">What is a Starter?</h2>
<p>Starters are basically a git repository in the form of a template that allows you to easily create a preconfigured app.</p>
<p>There’s nothing necessarily special about a Starter. At it’s core, it’s a Next.js app that’s already been set up a specific way and typically generalized so that anyone can use it.</p>
<p>For example, if you tend to build lots of apps the same way each time, you might have to repeat those same configuration steps every time you create a new app. </p>
<p>Instead, you can create a Starter from where you'll start your projects – and it'll eliminate the need to repeat those first steps each time.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’re going to build a basic Next.js Starter that will let you or anyone else quickly and easily create a new project with that Starter as a starting point.</p>
<p>While we won’t go too heavy into features, as the goal here is to learn about Starters, we’ll test this out by adding <a target="_blank" href="https://sass-lang.com/">Sass</a> to Next.js so someone can easily get started with CSS superpowers.</p>
<p>You can check out the <a target="_blank" href="https://github.com/colbyfayock/next-sass-starter">Starter</a> on GitHub: <a target="_blank" href="https://github.com/colbyfayock/next-sass-starter">github.com/colbyfayock/next-sass-starter</a>.</p>
<h2 id="heading-creating-a-new-nextjs-starter">Creating a new Next.js Starter</h2>
<p>To get started with creating a Starter, we need to start with a Next.js app.</p>
<p>We can do this by running the following command in whatever directory you want to create this in:</p>
<pre><code>yarn create next-app
# or
npx create-next-app
</code></pre><p>Once you run that, Next.js will ask you for a project name. While you can use whatever you like, Next.js Starters typically have a name pattern of <code>next-[name]-starter</code>.</p>
<p>So because we’re creating a Sass Starter, I might call it <code>next-sass-starter</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/command-line-new-nextjs-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js app in the terminal</em></p>
<p>Once Next.js has installed all of our dependencies, you’ll be ready to navigate to that folder and run the command to start your development server.</p>
<pre><code>yarn dev
# or
npm run dev
</code></pre><p>And once the development server starts up, we should be ready to go!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/new-nextjs-app-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js app in the browser</em></p>
<p>At this point, we pretty much have a basic Starter. As mentioned before, there really isn’t much that’s actually special with a Next.js Starter. So if we pushed this up to Github, we could immediately start using it “as is”.</p>
<p>You can test this out by running the following:</p>
<pre><code>yarn create next-app [project-name] -e [GitHub URL]
# or
npx create-next-app [project-name] -e [GitHub URL]
</code></pre><p>After running that, you should be set up with a new directory that has a project created from your Starter with all of the dependencies installed.</p>
<p>But we want to do more than that. Our goal is to add features that help get an app started with more than the default, so let’s add Sass.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/next-colbyfayock-starter/commit/ed87ce9d6585b2b642adf7e6878d0fc01bba05ef">Follow along with the commit!</a></p>
<h2 id="heading-adding-sass-to-a-nextjs-starter">Adding Sass to a Next.js Starter</h2>
<p>Note: For our example, we’re going to create a Sass starter as the name above might have implied. Feel free to add any features you want at this point, whether it includes Sass or not. </p>
<p>Remember – the goal here will be to provide something that we’ll be able to use when creating a new project with this Starter.</p>
<p>Next, we want to actually add Sass to our project. To get started, we want to install sass as a dependency:</p>
<pre><code>yarn add sass
# or
npm install sass
</code></pre><p>Next, because Next.js already looks for <code>.scss</code> as a file extension, we can simply update out two CSS files under the <code>styles</code> directory to <code>.scss</code>.</p>
<p>So change the following files:</p>
<pre><code>styles/globals.css =&gt; styles/globals.scss
styles/Home.module.css =&gt; styles/Home.module.scss
</code></pre><p>Next, we need to set up our import statements to recognize our new file extensions.</p>
<p>In <code>pages/_app.js</code>, update the styles import at the top to:</p>
<pre><code class="lang-scss">import '../styles/globals<span class="hljs-selector-class">.scss</span>'
</code></pre>
<p>And in <code>pages/index.js</code>, update the styles import to:</p>
<pre><code class="lang-scss">import styles from '../styles/Home<span class="hljs-selector-class">.module</span><span class="hljs-selector-class">.scss</span>'
</code></pre>
<p>At this point, you can start your development server and we should still see the default Next.js page.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/new-nextjs-app-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app should look the same</em></p>
<p>To see our Sass in action, we can update some of our classes to use nested styles instead of individual selectors.</p>
<p>Update all of the <code>.footer</code> selectors inside of <code>styles/Home.module.scss</code> to the following:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.footer</span> {

  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100px</span>;
  <span class="hljs-attribute">border-top</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#eaeaea</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;

  <span class="hljs-selector-tag">img</span> {
    <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0.5rem</span>;
  }

  <span class="hljs-selector-tag">a</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">align-items</span>: center;
  }

}
</code></pre>
<p>You can use the same nesting structure to update <code>.title</code> and <code>.card</code>.</p>
<p>We can also add the following to the top of our <code>styles/Home.module.css</code> file:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$color-primary</span>: <span class="hljs-number">#0070f3</span>;
</code></pre>
<p>And update all instances of the color in that file from <code>#0070f3</code> to <code>$color-primary</code>:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.title</span> {
  ...
  <span class="hljs-selector-tag">a</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$color-primary</span>;
</code></pre>
<p>If you reload the page, nothing will change. But update that variable to your favorite color like:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$color-primary</span>: blueviolet;
</code></pre>
<p>And now all of the colors change.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/nextjs-app-updated-colors.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Updated colors in the Next.js app</em></p>
<p>Finally, since we now have a Sass starter, let’s update the title of the page. Replace “Welcome to Next.js!” In <code>pages/index.js</code> to:</p>
<pre><code class="lang-jsx">&lt;h1 className={styles.title}&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://nextjs.org"</span>&gt;</span>Next.js<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span> Sass Starter
&lt;/h1&gt;
</code></pre>
<p>And now we have a Sass starting point!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/nextjs-app-updated-title.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Updated title in the Next.js app</em></p>
<p>Similar to before, you can test this out by creating a new project with your starter once all of the changes are on GitHub.</p>
<pre><code>yarn create next-app [project-name] -e [GitHub URL]
# or
npx create-next-app [project-name] -e [GitHub URL]
</code></pre><p><a target="_blank" href="https://github.com/colbyfayock/next-sass-starter/commit/56c5b67e8a383d8dc89c72d88cbe86adbac3edb8">Follow along with the commit!</a></p>
<h2 id="heading-setting-up-nextjs-starter-documentation-for-easy-setup">Setting up Next.js Starter documentation for easy setup</h2>
<p>Arguably one of the most important things about a Starter is documentation. </p>
<p>It might not be as important if you’re only using this yourself. But if you want other people to use it, you want them to know how to use it or else they’ll get stuck and become frustrated.</p>
<p>The most important part is getting the Starter set up. Setting up your Starter in a GitHub repo is a great first step. But if someone wants to use that Starter, they would have to clone or download that repo and then remove the git history.</p>
<p>Instead, you can add the command we used above in your <code>README.me</code> file to give people instructions on how to quickly get started, such as:</p>
<pre><code class="lang-mdx">## Getting Started

Run the following command to create a new project with this Starter:
</code></pre>
<p>yarn create next-app [project-name] -e https://github.com...</p>
<h1 id="heading-or">or</h1>
<p>npx create-next-app [project-name] -e https://github.com...</p>
<pre><code>
</code></pre><p>This will prevent people who might not understand how to do some of those things manually from getting stuck.</p>
<p>It’s also important to add any documentation of configuration options you’ve added.</p>
<p>If you’re adding some variables that allow you to change some site-wide features, make sure to add notes about those. </p>
<p>You ultimately want people to understand how to use the features you added to make their lives easier. If they don’t understand it, they may just rip that code out and do it manually.</p>
<p>Ultimately, creating and publishing a Starter is about making people’s lives easier. Whether it’s you coming back to your Starter a few months later or a swarm of new people looking to get productive, you’re giving them a better developer experience by adding good documentation.</p>
<h2 id="heading-some-other-things-to-consider">Some other things to consider</h2>
<h3 id="heading-generalizing-features-and-adding-configuration-for-a-nextjs-starter">Generalizing features and adding configuration for a Next.js Starter</h3>
<p>Adding features is a great way to make a Starter more likely to be used. If I used a Starter to create a new blog, I would love if that Starter included my name as an author and maybe even an About Me page.</p>
<p>But what I wouldn’t want is to have to replace someone else’s name 100 times throughout the code to update my own project. Not to mention, seeing that name on the Starter might make me feel more like it’s their blog rather than a template I can use for my project.</p>
<p>Consider starting off by using a generalized name throughout the project. Instead of using Colby Fayock’s Blog throughout the Starter, make it My Blog, which will make it feel less personal to the creator for the person using the Starter.</p>
<p>Also add some configuration options. It’s much easier to be able to update a single variable that would make my project include Colby Fayock instead of My Blog than it is to search all files to make that change manually.</p>
<h3 id="heading-choose-carefully-where-to-be-opinionated">Choose carefully where to be opinionated</h3>
<p>When using a tool like Sass, there is more than one way to use that tool. If you set up an incredibly specific and opinionated project structure, you’re alienating people using your Starter. </p>
<p>It'll either force them to rework the entire project or make them want to delete a bunch of code which might make them avoid wanting to use it in the future.</p>
<p>You can create opinionated Starters, but choose wisely where you inject those opinions. This will make your work usable by a larger group of people who want to be productive.</p>
<p>If you want to create something very opinionated, consider naming it something different and using the tool as part of the name. For example, I could create an opinionated Sass Starter called Colby’s Sassy Next.js Starter.</p>
<h2 id="heading-did-you-create-a-new-starter">Did you create a new Starter?</h2>
<p><a target="_blank" href="https://twitter.com/colbyfayock">Share with me on Twitter!</a></p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">? Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">? Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
