<?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[ maps - 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[ maps - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 09 Jul 2026 15:54:48 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/maps/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use OpenStreetMap as a Free Alternative to Google Maps ]]>
                </title>
                <description>
                    <![CDATA[ Google Maps has been the default choice for developers building location-based applications for years. But for many teams, especially those operating at scale, pricing has become a real concern. Googl ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-openstreetmap-free-alternative-to-google-maps/</link>
                <guid isPermaLink="false">69c41cdf10e664c5dacd6389</guid>
                
                    <category>
                        <![CDATA[ #LocationServices  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Aiyedogbon Abraham ]]>
                </dc:creator>
                <pubDate>Wed, 25 Mar 2026 17:35:27 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/0ab3655a-4212-451d-93e1-5c707ed1b07e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Google Maps has been the default choice for developers building location-based applications for years. But for many teams, especially those operating at scale, pricing has become a real concern.</p>
<p>Google Maps provides a $200 monthly credit, but beyond that, usage is billed per request. For applications like logistics, ride-hailing, or fleet tracking – where thousands of requests are made daily – costs can grow quickly depending on which APIs you use.</p>
<p>OpenStreetMap (OSM) offers a different approach. Instead of charging for access to map APIs, it provides free, open geographic data that you can build on.</p>
<p>In this guide, you'll learn what OpenStreetMap is, how it differs from Google Maps, and how to integrate it into a React application using Leaflet.</p>
<h2 id="heading-what-well-cover">What We'll Cover:</h2>
<ol>
<li><p><a href="#heading-what-is-openstreetmap">What is OpenStreetMap?</a></p>
</li>
<li><p><a href="#heading-why-choose-openstreetmap-over-google-maps">Why Choose OpenStreetMap Over Google Maps?</a></p>
</li>
<li><p><a href="#heading-understanding-the-open-street-map-ecosystem">Understanding the OpenStreetMap Ecosystem</a></p>
<ul>
<li><p><a href="#heading-data-layer-openstreetmap">Data Layer (OpenStreetMap)</a></p>
</li>
<li><p><a href="#heading-rendering-layer-leaflet-maplibre">Rendering Layer (Leaflet, MapLibre)</a></p>
</li>
<li><p><a href="#heading-services-layer">Services Layer</a></p>
</li>
<li><p><a href="#heading-how-everything-works-together">How Everything Works Together</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-how-to-integrate-openstreetmap-in-react-with-leaflet">How to Integrate OpenStreetMap in React with Leaflet</a></p>
</li>
<li><p><a href="#heading-how-to-add-geocoding-with-nominatim">How to Add Geocoding with Nominatim</a></p>
</li>
<li><p><a href="#heading-advanced-features">Advanced Features</a></p>
</li>
<li><p><a href="#heading-when-to-choose-openstreetmap-vs-google-maps">When to Choose OpenStreetMap vs Google Maps</a></p>
</li>
<li><p><a href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ol>
<h2 id="heading-what-is-openstreetmap">What is OpenStreetMap?</h2>
<p>OpenStreetMap is a free, open, and community-driven map of the world. Anyone can contribute to it, and anyone can use it.</p>
<p>Unlike Google Maps, which gives access through controlled APIs, OpenStreetMap gives you access to the underlying geographic data itself.</p>
<p>This data is structured in three main ways:</p>
<ol>
<li><p><strong>Nodes</strong>: single points (for example, a bus stop or a tree)</p>
</li>
<li><p><strong>Ways</strong>: lines or shapes made up of nodes (like roads or buildings)</p>
</li>
<li><p><strong>Relations</strong>: groups of nodes and ways that define more complex things (like routes or boundaries)</p>
</li>
</ol>
<p>Each of these elements includes tags (key-value pairs), such as:</p>
<pre><code class="language-plaintext">highway=residential
name=Allen Avenue
</code></pre>
<p>So instead of just displaying a map, OpenStreetMap lets you work with structured geographic data.</p>
<h3 id="heading-the-open-database-license-odbl">The Open Database License (ODbL)</h3>
<p>OpenStreetMap data is licensed under the ODbL. This means:</p>
<ul>
<li><p>You can use it for commercial or personal projects</p>
</li>
<li><p>You must give proper attribution</p>
</li>
</ul>
<p>This makes it especially useful for developers who want clarity around data ownership.</p>
<h2 id="heading-why-choose-openstreetmap-over-google-maps">Why Choose OpenStreetMap Over Google Maps?</h2>
<h3 id="heading-cost">Cost</h3>
<p>OpenStreetMap data is free to use. But it's important to be precise here: <strong>OpenStreetMap removes licensing costs, but not infrastructure costs.</strong></p>
<p>You may still need to pay for:</p>
<ul>
<li><p>Tile hosting</p>
</li>
<li><p>Geocoding services</p>
</li>
<li><p>Routing engines</p>
</li>
</ul>
<h3 id="heading-control">Control</h3>
<p>With Google Maps, you can't modify the data, and you rely entirely on Google's APIs</p>
<p>But with OpenStreetMap, you can download and store the data, modify it, and build custom solutions on top of it.</p>
<h3 id="heading-customization">Customization</h3>
<p>OpenStreetMap gives you more flexibility:</p>
<ul>
<li><p>You control how maps are rendered</p>
</li>
<li><p>You can choose or build your own map styles</p>
</li>
<li><p>You can create domain-specific maps</p>
</li>
</ul>
<h3 id="heading-adoption">Adoption</h3>
<p>OpenStreetMap is widely used. Companies like Meta and Microsoft contribute to it, and many platforms rely on it directly or indirectly.</p>
<p>This shows that the ecosystem is mature and reliable.</p>
<h2 id="heading-understanding-the-openstreetmap-ecosystem">Understanding the OpenStreetMap Ecosystem</h2>
<p>A common mistake is to think that OpenStreetMap works like a single API. It doesn't.</p>
<p>Instead, it works as a set of layers, where each layer handles a different responsibility.</p>
<h3 id="heading-data-layer-openstreetmap">Data Layer (OpenStreetMap)</h3>
<p>This is the foundation. It contains all the raw geographic data:</p>
<ul>
<li><p>Roads</p>
</li>
<li><p>Buildings</p>
</li>
<li><p>Landmarks</p>
</li>
<li><p>Boundaries</p>
</li>
</ul>
<p>This is what you are ultimately working with.</p>
<h3 id="heading-rendering-layer-leaflet-maplibre">Rendering Layer (Leaflet, MapLibre)</h3>
<p>Raw data isn't visual. It needs to be turned into something users can see.</p>
<p>There are two main approaches:</p>
<ol>
<li><p><strong>Raster tiles</strong> (used by Leaflet): pre-rendered images</p>
</li>
<li><p><strong>Vector tiles</strong> (used by MapLibre): raw geometry styled in the browser</p>
</li>
</ol>
<p>Leaflet uses raster tiles by default, which makes it simple and fast to start with.</p>
<h3 id="heading-services-layer">Services Layer</h3>
<p>This is what makes your map interactive. <strong>Geocoding</strong> converts addresses into coordinates, while <strong>reverse geocoding</strong> converts coordinates into addresses.</p>
<p><strong>Routing</strong> calculates directions between points, and <strong>tile servers</strong> provide the actual map visuals.</p>
<h3 id="heading-how-everything-works-together">How Everything Works Together</h3>
<p>When a user searches for a place:</p>
<ol>
<li><p>The user enters a location</p>
</li>
<li><p>A geocoding service converts it into coordinates</p>
</li>
<li><p>The map updates its position</p>
</li>
<li><p>A tile server provides the visual map</p>
</li>
</ol>
<p>Each part is separate, but they work together to create the full experience.</p>
<h2 id="heading-how-to-integrate-openstreetmap-in-react-with-leaflet">How to Integrate OpenStreetMap in React with Leaflet</h2>
<p>Let's build a simple map.</p>
<h3 id="heading-step-1-create-a-react-app">Step 1: Create a React App</h3>
<pre><code class="language-bash">npm create vite@latest osm-app -- --template react
cd osm-app
npm install
</code></pre>
<h3 id="heading-step-2-install-dependencies">Step 2: Install Dependencies</h3>
<pre><code class="language-bash">npm install leaflet react-leaflet
npm install --save-dev @types/leaflet
</code></pre>
<h3 id="heading-step-3-import-leaflet-css">Step 3: Import Leaflet CSS</h3>
<pre><code class="language-javascript">import 'leaflet/dist/leaflet.css';
</code></pre>
<p>This is required for the map to display correctly.</p>
<h3 id="heading-step-4-create-a-map-component">Step 4: Create a Map Component</h3>
<pre><code class="language-javascript">import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';

function Map() {
  const position = [51.505, -0.09]; // latitude, longitude

  return (
    &lt;MapContainer
      center={position}
      zoom={13}
      style={{ height: '100vh' }}
    &gt;
      &lt;TileLayer
        attribution='&amp;copy; &lt;a href="https://www.openstreetmap.org/copyright"&gt;OpenStreetMap&lt;/a&gt; contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      /&gt;
      &lt;Marker position={position}&gt;
        &lt;Popup&gt;Hello from OpenStreetMap&lt;/Popup&gt;
      &lt;/Marker&gt;
    &lt;/MapContainer&gt;
  );
}

export default Map;
</code></pre>
<p>Let's break down the important parts here:</p>
<p><code>MapContainer</code> initializes the map.</p>
<ul>
<li><p><code>center</code> is where the map starts</p>
</li>
<li><p><code>zoom</code> is how close the view is</p>
</li>
<li><p><code>style</code> must include height, or the map won't show</p>
</li>
</ul>
<p><code>TileLayer</code> defines where the map visuals come from.</p>
<ul>
<li><p><code>{z}</code> is the zoom level</p>
</li>
<li><p><code>{x}</code>, <code>{y}</code> are the tile coordinates</p>
</li>
<li><p><code>{s}</code> is the subdomain</p>
</li>
</ul>
<p>Each tile is a small image (usually 256×256 pixels), and Leaflet combines them to form the full map.</p>
<p><code>Marker</code> adds a point on the map at a specific coordinate.</p>
<p><code>Popup</code> displays information when the marker is clicked.</p>
<h4 id="heading-important-note">Important note:</h4>
<p>The default OpenStreetMap tile server:</p>
<pre><code class="language-plaintext">https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png
</code></pre>
<p>is meant for learning, demos, and low-traffic apps. For production, you should use a dedicated provider or your own tile server.</p>
<h2 id="heading-how-to-add-geocoding-with-nominatim">How to Add Geocoding with Nominatim</h2>
<p>Nominatim is OpenStreetMap's geocoding service. It allows you to convert addresses into coordinates and coordinates into readable locations.</p>
<h3 id="heading-custom-hook-for-geocoding">Custom Hook for Geocoding</h3>
<pre><code class="language-javascript">import { useState } from 'react';

export function useGeocoding() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const searchAddress = async (query) =&gt; {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch(
        `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&amp;format=json&amp;limit=5`,
        {
          headers: {
            'User-Agent': 'YourAppName/1.0'
          }
        }
      );

      if (!response.ok) {
        throw new Error('Request failed');
      }

      const data = await response.json();
      setLoading(false);
      return data;
    } catch (err) {
      setError(err.message);
      setLoading(false);
      return [];
    }
  };

  return { searchAddress, loading, error };
}
</code></pre>
<p>In this code:</p>
<ul>
<li><p><code>useState</code> manages loading and error states</p>
</li>
<li><p><code>encodeURIComponent</code> ensures safe URLs</p>
</li>
<li><p><code>User-Agent</code> is required by Nominatim</p>
</li>
<li><p><code>response.json()</code> converts response into usable data</p>
</li>
</ul>
<p>Nominatim returns coordinates as strings, so you have to convert them before using them.</p>
<h3 id="heading-important-usage-rules">Important Usage Rules</h3>
<p>The public Nominatim service:</p>
<ul>
<li><p>Allows about 1 request per second</p>
</li>
<li><p>Requires proper identification</p>
</li>
<li><p>May block excessive usage</p>
</li>
</ul>
<p>You should debounce user input, cache results, and avoid repeated requests.</p>
<h3 id="heading-creating-a-search-component">Creating a Search Component</h3>
<p>The search component lets users type an address or place name and get matching locations via Nominatim. It includes a text input and a submit button.</p>
<p>When the form is submitted, it calls our <code>searchAddress</code> function (from the <code>useGeocoding</code> hook), which fetches up to 5 address results. These results are displayed below the input as clickable items.</p>
<p>When the user clicks a result, the component parses the returned latitude and longitude into numbers and passes them (along with a display name) up to the parent component via the <code>onLocationSelect</code> callback. This will allow the parent (for example, the map) to update its center based on the chosen location.</p>
<pre><code class="language-javascript">function SearchBox({ onLocationSelect }) {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const { searchAddress, loading } = useGeocoding();

  const handleSearch = async (e) =&gt; {
    e.preventDefault();
    if (!query.trim()) return;

    const data = await searchAddress(query);
    setResults(data);
  };

  const selectLocation = (result) =&gt; {
    onLocationSelect({
      lat: parseFloat(result.lat),
      lon: parseFloat(result.lon),
      name: result.display_name
    });
  };

  return (
    &lt;div&gt;
      &lt;form onSubmit={handleSearch}&gt;
        &lt;input
          value={query}
          onChange={(e) =&gt; setQuery(e.target.value)}
          placeholder="Search location"
        /&gt;
        &lt;button type="submit"&gt;
          {loading ? 'Searching...' : 'Search'}
        &lt;/button&gt;
      &lt;/form&gt;

      &lt;div&gt;
        {results.map((result) =&gt; (
          &lt;div key={result.place_id} onClick={() =&gt; selectLocation(result)}&gt;
            {result.display_name}
          &lt;/div&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>Key concepts here:</p>
<ul>
<li><p><code>useState</code> stores the current input (<code>query</code>) and the array of search <code>results</code>.</p>
</li>
<li><p><code>e.preventDefault()</code> stops the form submission from reloading the page.</p>
</li>
<li><p>Calling <code>searchAddress(query)</code> fetches geocoding results from Nominatim.</p>
</li>
<li><p><code>parseFloat()</code> converts the returned <code>lat</code>/<code>lon</code> strings into JavaScript numbers before using them.</p>
</li>
<li><p><code>onLocationSelect</code> is a callback prop that sends the selected coordinates and name back to the parent component (for example to update the map).</p>
</li>
</ul>
<h2 id="heading-advanced-features">Advanced Features</h2>
<p>We can further extend the map app by adding more advanced functionality. For example:</p>
<h3 id="heading-routing-osrm-graphhopper">Routing (OSRM, GraphHopper)</h3>
<p>You can integrate turn-by-turn routing on your map. A common solution is to use a library like <a href="https://www.liedman.net/leaflet-routing-machine/">Leaflet Routing Machine</a>, which supports OSRM out of the box and has plugins for GraphHopper. This adds a route UI control where users enter start and end points, and the library fetches a route from one of these engines to draw on the map.</p>
<h3 id="heading-custom-tile-providers-carto-maptiler-and-so-on"><strong>Custom Tile Providers (Carto, MapTiler, and so on)</strong></h3>
<p>Instead of the standard <a href="http://tile.openstreetmap.org"><code>tile.openstreetmap.org</code></a>, you can use hosted tile services that offer OSM-based maps. For example, Carto and MapTiler both provide tile APIs (often with custom style options and higher usage limits).</p>
<p>Carto, MapTiler, and similar services are listed among the providers that allow free usage of OSM tiles. By using a custom tile provider, you gain flexibility in map design and avoid hitting the public server’s limits.</p>
<h3 id="heading-vector-maps-maplibre-gl-js">Vector Maps (MapLibre GL JS)</h3>
<p>You can switch from raster tiles to vector tiles for even richer interactivity. Vector tiles send raw map data (geometries and attributes) to the client, which are then rendered in the browser. This allows dynamic styling and advanced features: for instance, you can change the map’s theme on the fly (for example, switch to a “dark mode” style at night) or highlight certain features like bike lanes more prominently.</p>
<p>Libraries like MapLibre GL JS (the open-source successor to Mapbox GL) can display OSM vector tiles with highly customizable styles and smooth zooming/rotation. This makes your map more responsive and adaptable to different use cases.</p>
<h2 id="heading-when-to-choose-openstreetmap-vs-google-maps">When to Choose OpenStreetMap vs Google Maps</h2>
<h3 id="heading-choose-openstreetmap-when">Choose OpenStreetMap when:</h3>
<ul>
<li><p>You need flexibility</p>
</li>
<li><p>You want to reduce costs at scale</p>
</li>
<li><p>You want control over data</p>
</li>
</ul>
<h3 id="heading-choose-google-maps-when">Choose Google Maps when:</h3>
<ul>
<li><p>You want an all-in-one solution</p>
</li>
<li><p>You need features like Street View</p>
</li>
<li><p>You want minimal setup</p>
</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>OpenStreetMap offers a powerful alternative to Google Maps for developers who need cost control, data ownership, and customization. While it requires understanding different components, the flexibility it provides is worth the learning curve.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Does Anyone Have a Map? How Web Development Roadmaps Help You Learn to Code ]]>
                </title>
                <description>
                    <![CDATA[ By Kevin Cunningham I'm a fan of musical theatre. The last show I saw in London's West End before Covid was Dear Evan Hansen. It's a show about teen suicide, parenting and social media (sounds a blast, eh?).  The show opens with a song sung by two mo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-map-for-web-development/</link>
                <guid isPermaLink="false">66d45f64706b9fb1c166b985</guid>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 04 Jan 2021 16:12:26 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5fe363b3e6787e0983942425.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Kevin Cunningham</p>
<p>I'm a fan of musical theatre. The last show I saw in London's West End before Covid was Dear Evan Hansen. It's a show about teen suicide, parenting and social media (sounds a blast, eh?). </p>
<p>The show opens with a song sung by two mothers, asking if anyone has a map.</p>
<blockquote>
<p><em>Does anybody have a map?</em><br><em>Anybody maybe happen to know how the hell to do this?</em><br><em>I don't know if you can tell</em><br><em>But this is me just pretending to know</em> </p>
</blockquote>
<p>Maps are pretty amazing pieces of technology. They provide a way to get an overview of what you know and what you don't know. </p>
<p>As tools for navigation, they allow us to be able to plot and plan routes. You can see which parts of the journey are going to be more challenging and which you don't know enough about.</p>
<p>As tools for discussion, they help reduce confusion and increase clarity. Which hill are you talking about exactly? How far away is that? How long will it take to get there?</p>
<p>As tools for discovery, they help show where more investigation is needed. In ancient times, dragons or sea monsters were often drawn on the parts that were unknown. Our satellite imagery is more accurate but can also make us think we know everything.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Carta_Marina-lightened.jpg/512px-Carta_Marina-lightened.jpg" alt="Carta Marina-lightened" width="600" height="400" loading="lazy">
<em>Carta Marina - map of the Nordic countries with sea monsters to the west</em></p>
<p>The moms in the song wanted some way to navigate through parenting, to identify smooth paths and rough terrain. </p>
<p>So how does this relate to web development? </p>
<h2 id="heading-the-freecodecamp-curriculum">The FreeCodeCamp Curriculum</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/Screenshot-2021-01-03-at-05.45.38.png" alt="Image" width="600" height="400" loading="lazy">
<em>freeCodeCamp Certifications</em></p>
<p>The freeCodeCamp curriculum is pretty great. It traces an outline of the most important aspects of web development today. </p>
<p>The way I've placed each of the certifications in the image above suggests they are separate and distinct. In fact, they overlap and use core pieces of knowledge throughout.</p>
<p>Read through the lesson titles and headings. They draw out the high notes - frontend, backend, algorithms, data, HTML, CSS, JavaScript, Python and more. Seen together, these draw a map of the space. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/Screenshot-2021-01-03-at-05.59.48.png" alt="Image" width="600" height="400" loading="lazy">
<em>Possible map of the FCC curriculum</em></p>
<p>There are other maps around. The <a target="_blank" href="https://github.com/kamranahmedse/developer-roadmap">web-developer roadmaps</a> that Kamran Ahmed has been keeping updated are pretty epic. These have the advantage that they look a bit more like maps, but they can feel overwhelming. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/image-18.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-whats-the-purpose-of-a-map">What's the Purpose of a Map?</h2>
<p>I saw earlier versions of Kamran's roadmaps a few years ago and they made me feel a bit overwhelmed. There was so much I needed to know to become a developer. At least, that was how it felt. </p>
<p>Over time, though, I've begun comparing it to flicking through an atlas or Google maps. I love seeing how countries change as you cross a river or mountain range. I enjoy tracing rivers over whole continents and imagine walking the mountain ranges. </p>
<p>I don't feel inadequate that I haven't visited all of these countries or that I can't remember every country or every capital. Instead, I feel empowered and excited by knowing roughly where countries are and how they fit together. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/01/image-19.png" alt="A map of the world" width="600" height="400" loading="lazy">
<em>Map of the world</em></p>
<p>I live in Brighton, and if I want to meet a friend for coffee, then a street map is going to be much more useful.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Location_map_Brighton_central.png/256px-Location_map_Brighton_central.png" alt="Location map Brighton central" width="600" height="400" loading="lazy">
<em>Street map of central Brighton</em></p>
<p>But, it we were going for a walk in the countryside, tracing a river for example, then yet another type of map is needed.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/River_Frome.jpg/512px-River_Frome.jpg" alt="River Frome" width="600" height="400" loading="lazy">
<em>Map of the River Frome</em></p>
<p>I find that this is the same for any learning project. For web development, you can use a map that already exists (like the freeCodeCamp curriculum or Kamran's map) or you can begin to develop your own.</p>
<p>Like looking at countries, you can zoom out and see how the main pieces hold together. At this level, you can see how things fit together. </p>
<p>Here we have large and encompassing topics like "front-end" or "quality assurance". We don't need to know everything to about these topics but we can see how they relate to others.</p>
<p>Like looking at cities, you can zoom in to see how a particular technology works. How does JavaScript work? What is the syntax? What are the rules and patterns? </p>
<p>And like tracing rivers, you can see how a practice or convention is handled in the front-end, back-end and everywhere in between. </p>
<p>Here we might think about how data flows between the different parts of a web application. We can imagine the journey of the data from the user, to the front-end, to the database and back out again.</p>
<h2 id="heading-how-to-become-a-well-equipped-explorer">How to Become a Well-equipped Explorer</h2>
<p>I'm a largely self-taught developer. Early in my learning career, I would hear whispers of an interesting, cool or new technology and dive in. I'd read books, do tutorials and build small example projects. However, they didn't connect together in my mind. </p>
<p>To continue with the mapping metaphor, I was being teleported randomly into a city, exploring and then leaving again. Over years, I had ideas about lots of cities and no idea how they fit into countries and how the rivers and landscapes linked them together.</p>
<p>It was only when I had a map of the space that I understood how the knowledge I had fit together. I could see where the gaps in my understanding were and direct my efforts in the right direction. </p>
<p>I realised that I didn't need to explore the whole world but I could have an awareness of what was out there. </p>
<h2 id="heading-what-about-you">What about you?</h2>
<p>What maps are you using to help you with your development journey? Have you drawn a dragon over back-end technologies and decided you don't want to go near them? Or maybe there is a sea monster hovering over CSS or algorithms? </p>
<p>Excellent developers are always learning. They are studying their maps and deciding where they'd like to explore next. </p>
<p>You don't have to know the whole world but knowing what you know (and what you don't) can help take your skills to the next level.   </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Travel Bucket List Map with Gatsby, React Leaflet, & Hygraph ]]>
                </title>
                <description>
                    <![CDATA[ Traveling is fun and we all have a lot of places we want to visit, but rarely do we have time to do it all at once. That’s what bucket lists are for! How can we create a custom mapping app that we can show all of our the destinations ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-travel-bucket-list-map-with-gatsby-react-leaflet-graphcms/</link>
                <guid isPermaLink="false">66b8e3580cedc1f2a4f7069b</guid>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ cms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ graphcms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ headless cms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Travel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 23 Jun 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/travel-bucket-list.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Traveling is fun and we all have a lot of places we want to visit, but rarely do we have time to do it all at once. That’s what bucket lists are for! How can we create a custom mapping app that we can show all of our the destinations on our bucket list?</p>
<p>Note: As of July 2022, GraphCMS is now <a target="_blank" href="https://hygraph.com/">Hygraph</a>.</p>
<ul>
<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-1-creating-a-new-app-with-gatsby-starter-leaflet">Step 1: Creating a new app with Gatsby Starter Leaflet</a></li>
<li><a class="post-section-overview" href="#heading-step-2-creating-and-managing-a-list-of-travel-locations-with-graphcms">Step 2: Creating and managing a list of travel locations with GraphCMS</a></li>
<li><a class="post-section-overview" href="#heading-step-3-querying-our-graphcms-location-data-with-gatsby-and-graphql">Step 3: Querying our GraphCMS location data with Gatsby and GraphQL</a></li>
<li><a class="post-section-overview" href="#heading-step-4-creating-a-bucket-list-of-destinations-and-adding-them-to-the-map">Step 4: Creating a bucket list of destinations and adding them to the map</a></li>
<li><a class="post-section-overview" href="#heading-what-else-other-features-can-we-add-to-our-app">What else other features can we add to our app?</a></li>
<li><a class="post-section-overview" href="#heading-want-to-learn-more-about-maps">Want to learn more about maps?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/isbr52VKjb0" 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-we-going-to-build">What are we going to build?</h2>
<p>We’re going to build a mapping app with <a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a> managed by a CMS that will both display markers on a map and show our locations in a simple text-based list for our bucket list locations.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/travel-bucket-list-demo.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Demo of a Travel Bucket List mapping app</em></p>
<p>We’ll spin up the app with a <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Gatsby Starter for Leaflet</a> and then we’ll use <a target="_blank" href="https://graphcms.com/">GraphCMS</a> to create and manage the list of locations for our map!</p>
<h2 id="heading-woah-a-mapping-app">Woah, a mapping app?</h2>
<p>Yup. If you haven't played with maps before, don't be discouraged! It's not as bad as you probably think. If you'd rather start with mapping basics, you can  <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">read more about how mapping works</a>  first.</p>
<h2 id="heading-step-1-creating-a-new-app-with-gatsby-starter-leaflet">Step 1: Creating a new app with Gatsby Starter Leaflet</h2>
<p>We’ll start off with Gatsby Starter Leaflet. This is going to give us a basic React application with our mapping tools already built in.</p>
<h3 id="heading-creating-a-new-gatsby-app-with-gatsby-starter-leaflet">Creating a new Gatsby app with Gatsby Starter Leaflet</h3>
<p>To get started, navigate to where you want to create your new app and run:</p>
<pre><code class="lang-shell">gatsby new my-travel-bucket-list https://github.com/colbyfayock/gatsby-starter-leaflet
</code></pre>
<p><em>Note: you can replace <code>my-travel-bucket-list</code> with whatever you want. This will be used to create the new folder for the app.</em></p>
<p>Once you run that, Gatsby will pull down the Starter and install the dependencies. After it’s complete, navigate to that directory and run the development command:</p>
<pre><code class="lang-shell">cd my-travel-bucket-list
yarn develop
# or
npm run develop
</code></pre>
<p>Once it’s finished location, your app should be ready to go!</p>
<h3 id="heading-cleaning-our-some-demo-code">Cleaning our some demo code</h3>
<p>Because we’re using a Starter, it has a little bit of demo code. Let’s clean that out to avoid any confusion.</p>
<p>Open up the <code>src/pages/index.js</code> file.</p>
<p>First, remove everything inside of <code>mapEffect</code> except the first line and set up an alias for <code>leafletElement</code> to <code>map</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement: map } = {}</span>) </span>{
  <span class="hljs-keyword">if</span> ( !map ) <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>With that gone, we can remove the <code>markerRef</code> definition at the top of the <code>IndexPage</code> component, remove the <code>ref={markerRef}</code> prop from our <code>&lt;Marker&gt;</code> component, and the <code>useRef</code> import next to React.</p>
<p>Now, we can remove all of the variables that start with <code>popup</code> and <code>time</code>, including:</p>
<ul>
<li>timeToZoom</li>
<li>timeToOpenPopupAfterZoom</li>
<li>timeToUpdatePopupAfterZoom</li>
<li>popupContentHello</li>
<li>popupContentGatsby</li>
</ul>
<p>Lastly, you can remove all of the following lines:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> L <span class="hljs-keyword">from</span> <span class="hljs-string">'leaflet'</span>;
...
import { promiseToFlyTo, getCurrentLocation } <span class="hljs-keyword">from</span> <span class="hljs-string">'lib/map'</span>;
...
import gatsby_astronaut <span class="hljs-keyword">from</span> <span class="hljs-string">'assets/images/gatsby-astronaut.jpg'</span>;
...
const ZOOM = <span class="hljs-number">10</span>;
</code></pre>
<p>Once done, we should be ready to go with a basic app with a map!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/new-app-gatsby-starter-leaflet.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New app with Gatsby Starter Leaflet</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-travel-bucket-list/commit/63eed5a7a208ede6f8eeec44e0c08b594b407360">Follow along with the commit!</a></p>
<h2 id="heading-step-2-creating-and-managing-a-list-of-travel-locations-with-graphcms">Step 2: Creating and managing a list of travel locations with GraphCMS</h2>
<h3 id="heading-creating-a-graphcms-account">Creating a GraphCMS account</h3>
<p>To get started with GraphCMS, you’ll need an account. I’m not going to walk you through this part, but the good news is they have a generous free tier that makes it easy to sign up for us to use for our demo!</p>
<p><a target="_blank" href="https://app.graphcms.com/signup">Sign up for GraphCMS</a></p>
<p>Alternatively, if you already have an account, you can make sure you’re logged in.</p>
<h3 id="heading-creating-a-new-graphcms-project">Creating a new GraphCMS project</h3>
<p>Once logged in, we’ll want to create a new project. We’re going to create one manually, so once at the <a target="_blank" href="https://app.graphcms.com/">GraphCMS Dashboard</a>, select <strong>Create new project</strong>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-create-new-project.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new project in GraphCMS</em></p>
<p>Here, you can enter whatever you’d like for the <strong>Name</strong> and <strong>Description</strong> such as:</p>
<ul>
<li>Name: My Travel Bucket List</li>
<li>Description: The locations that I want to travel to some day!</li>
</ul>
<p>Below that you’ll see a map where you’ll select a <strong>Region</strong>. This is where your database data will live, so while it probably doesn’t matter too much for our purposes, you can choose the one that’s closest to you.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-configure-new-project.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Configuring a new project in GraphCMS</em></p>
<p>After you select your options, go ahead and click <strong>Create Project</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-select-plan.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting the Personal plan in GraphCMS</em></p>
<p>Next, you’ll be presented with billing options. Since we’re just creating a demo, under <strong>Personal</strong> select <strong>Continue</strong> at which point we’ll be dropped into our new GraphCMS project dashboard.</p>
<h3 id="heading-creating-a-new-content-model-schema-with-graphcms">Creating a new Content Model Schema with GraphCMS</h3>
<p>In GraphCMS, a Content Model refers to a specific type of data that has specific properties associated with it. In our case, our Model will be a Destination, which will be defined by a Name and a Location.</p>
<p>First, navigate to the <strong>Schema</strong> section of GraphCMS in the left sidebar and select <strong>Create Model</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-create-new-schema-model.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new Schema Model in GraphCMS</em></p>
<p>Once selected, you’ll see a popup that asks for a bit more information. Here, you can type in “Destination” as the <strong>Display Name</strong>, which will also fill in most of the other fields. We’ll leave those as is.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-configure-new-content-model.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Configuring a new Model in GraphCMS</em></p>
<p>Feel free to add a description if you’d like, but it’s not required. Then select <strong>Create model</strong>.</p>
<p>Now that we have our Model, we need our properties.</p>
<p>First, select <strong>Single line text</strong> in the right list of fields and add a <strong>Display Name</strong> of “Name”. This will also fill out <strong>App Id</strong> which you can leave as is. Then click <strong>Create</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-configure-text-field.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding and configuring a new text field in GraphCMS</em></p>
<p>Next, scroll down in the field options on the right and under <strong>Location</strong> select <strong>Map</strong>. Add “Location” as the <strong>Display Name</strong>, which will set the <strong>App Id</strong> as “location” which you can leave as is. Then same as before, click <strong>Create</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-configure-new-map-field.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding and configuring a new map field in GraphCMS</em></p>
<p>Now we have a Content Model which we’ll use to create our locations!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-destination-content-model.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Destination content Model in GraphCMS</em></p>
<h3 id="heading-creating-our-locations">Creating our locations</h3>
<p>Finally, let’s create our locations. Navigate over to <strong>Content</strong> in the GraphCMS dashboard, make sure you’ve selected <strong>Destination</strong> under <strong>System</strong> (should be the only one), and select <strong>Create New</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-add-new-content.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Create new Destination Content in GraphCMS</em></p>
<p>Now we can start adding all of our locations! First, add the name of your location in the <strong>Name</strong> field, then you can use the <strong>Search</strong> box under <strong>Location</strong> to find that location on the map.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-create-new-destination-content-item.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding a new Destination Content item in GraphCMS</em></p>
<p>Once you’re good, hit <strong>Save and publish</strong>. This will create your first location!</p>
<p>Follow those same steps and create as many locations as you want.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-destination-content-items.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>List of Destination Content items in GraphCMS</em></p>
<p>We’ll use these for our map and bucket list.</p>
<h2 id="heading-step-3-querying-our-graphcms-location-data-with-gatsby-and-graphql">Step 3: Querying our GraphCMS location data with Gatsby and GraphQL</h2>
<p>Now that we have our locations, let’s use them!</p>
<h3 id="heading-adding-a-plugin-to-gatsby-to-query-our-graphql-data">Adding a plugin to Gatsby to query our GraphQL data</h3>
<p>First, we need to <a target="_blank" href="https://www.gatsbyjs.org/packages/gatsby-source-graphql/">add a new plugin</a> to our Gatsby project to query our GraphQL data. In your terminal make sure your development server isn’t running and run:</p>
<pre><code class="lang-shell">yarn add gatsby-source-graphql
# or
npm install gatsby-source-graphql
</code></pre>
<p>Next, open up your <code>gatsby-config.js</code> file in the root of your project and add the following to your plugins:</p>
<pre><code class="lang-json">{
  resolve: 'gatsby-source-graphql',
  options: {
    typeName: 'GCMS',
    fieldName: 'gcms',
    url: '[API ENDPOINT]',
  }
}
</code></pre>
<p>This will be what sources our data from GraphCMS, but we need an endpoint.</p>
<h3 id="heading-finding-our-api-endpoint-for-graphcms">Finding our API endpoint for GraphCMS</h3>
<p>Open back up your browser and head over to your GraphCMS project. After selecting <strong>Settings</strong> in the left navigation, select <strong>API Access</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-api-access.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>API Access in GraphCMS</em></p>
<p>Before we copy our API Endpoint, first we need to update our permissions so we can query our API. Under <strong>Public API Permissions</strong>, check the box next to <strong>Content from stage Published</strong> and click <strong>Save</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-configure-api-access.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Configuring API permissions in GraphCMS</em></p>
<p>Next, copy the URL under <strong>Endpoints</strong>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/graphcms-copy-api-access-endpoint.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Copying API Endpoint in GraphCMS</em></p>
<p>And paste that in to your <code>gatsby-config.js</code> file that we modified above:</p>
<pre><code class="lang-json">{
  resolve: 'gatsby-source-graphql',
  options: {
    typeName: 'GCMS',
    fieldName: 'gcms',
    url: 'https:<span class="hljs-comment">//[region-id].graphcms.com/v2/[project-id]/master',</span>
  },
},
</code></pre>
<p><em>Note: your URL will have actual values inside of <code>[region-id]</code> and <code>[project-id]</code>.</em></p>
<p>Save your <code>gatsby-config.js</code> file and start your development server backup (<code>yarn develop</code>) and we’re ready to go!</p>
<h3 id="heading-querying-our-locations-via-graphql">Querying our locations via GraphQL</h3>
<p>Finally, let’s actually query our data so that we’ll be able to use it in our app.</p>
<p>We’re going to create a new <a target="_blank" href="https://reactjs.org/docs/hooks-reference.html">React Hook</a> that we’ll be able to use to grab our locations anywhere within our app.</p>
<p>Under <code>src/hooks/index.js</code>, add the following line to the existing list:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> { <span class="hljs-keyword">default</span> <span class="hljs-keyword">as</span> useDestinations } <span class="hljs-keyword">from</span> <span class="hljs-string">'./useDestinations'</span>;
</code></pre>
<p>This will allow us to more conveniently import our hook which we’ll create next.</p>
<p>Under <code>src/hooks</code>, create a new file <code>useDestinations.js</code> and paste in this code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { graphql, useStaticQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'gatsby'</span>;

<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">useDestinations</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { gcms = {} } = useStaticQuery( graphql<span class="hljs-string">`
    query {
      gcms {
        destinations {
          id
          name
          location {
            latitude
            longitude
          }
        }
      }
    }
  `</span> );

  <span class="hljs-keyword">let</span> { destinations } = gcms;

  <span class="hljs-keyword">return</span> {
    destinations,
  };
}
</code></pre>
<p>Here, we’re:</p>
<ul>
<li>Importing the <code>graphql</code> and <code>useStaticQuery</code> utilities from Gatsby</li>
<li>We’re creating a new function (or hook) that is exported by default</li>
<li>In that function, we’re using <code>useStaticQuery</code> to create a new GraphQL query which asks GraphCMS to return the data structure we defined.</li>
<li>That query returns a value which we destructure immediately to grab the <code>gmcs</code> object</li>
<li>We destructure <code>destinations</code> from <code>gmcs</code> and return it as part of a new object from our hook</li>
</ul>
<p>With this, we can now use our hook anywhere in our app!</p>
<p>Head over to your <code>src/pages/index.js</code> file, first import our new hook:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useDestinations } <span class="hljs-keyword">from</span> <span class="hljs-string">'hooks'</span>;
</code></pre>
<p>And at the top of the <code>IndexPage</code> component, query our data:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { destinations } = useDestinations();
</code></pre>
<p>This puts all of our locations into the <code>destinations</code> variable. We can test that this works by console logging it out:</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'destinations'</span>, destinations);
</code></pre>
<p>And once we open up our browser and look in our web developer tools console, we can see our location data!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/gatsby-starter-leaflet-logging-graphcms-destinations.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Logging destinations data to the web console</em></p>
<h2 id="heading-step-4-creating-a-bucket-list-of-destinations-and-adding-them-to-the-map">Step 4: Creating a bucket list of destinations and adding them to the map</h2>
<p>We’re going to start with creating a simple text list of our destinations. This will let us see all of our destinations in an easy to read format.</p>
<h3 id="heading-creating-a-text-list-of-our-destinations">Creating a text list of our destinations</h3>
<p>Inside of our <code>IndexPage</code> and above “Still Getting Started?”, let’s add the following code:</p>
<pre><code class="lang-jsx">&lt;h2&gt;My Destinations&lt;/h2&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
  { destinations.map(destination =&gt; {
    const { id, name } = destination;
    return <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>{ name }<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  })}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
</code></pre>
<p>This code:</p>
<ul>
<li>Adds a new header for our list</li>
<li>Creates a new unordered list</li>
<li>Loops through our <code>destinations</code> and creates a new list item for each destination that include’s the location’s name</li>
</ul>
<p>Once we hit save and reload, we should see our list under our map!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/app-adding-list-of-destinations.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New basic list of destinations in the app</em></p>
<p>The list looks a little odd though right? We probably want to format it a little better to fit into the page.</p>
<p>Open up <code>src/assets/stylesheets/pages/_home.scss</code> and inside of the <code>.home-start</code> class, add:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.home-start</span> {

  ...

  <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">1.2em</span> <span class="hljs-number">0</span>;
  }
</code></pre>
<p>Let’s also modify the <code>h2</code> to space things out a little better:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.home-start</span> {

  ...

  <span class="hljs-selector-tag">h2</span> {

    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">2em</span>;

    &amp;<span class="hljs-selector-pseudo">:first-child</span> {
      <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">0</span>;
    }

  }
</code></pre>
<p>Once you hit save and reload, it should look a little better.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/app-fixing-styles-list-of-destinations.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Destinations in the app with cleaned up styles</em></p>
<p>Feel free to make additional changes, but we’ll leave it there for now.</p>
<h3 id="heading-adding-our-destinations-to-the-map">Adding our destinations to the map</h3>
<p>Now we can finally add our destinations to the map!</p>
<p>Inside of our <code>&lt;Map&gt;</code> component, we already have a <code>&lt;Marker&gt;</code>. This allows us to easily add a marker to the map given a position. We’ll take this concept and combine it with our text list to add our locations to the map.</p>
<p>Let’s update our <code>&lt;Map&gt;</code> code to match the following:</p>
<pre><code class="lang-jsx">&lt;<span class="hljs-built_in">Map</span> {...mapSettings}&gt;
  { destinations.map(<span class="hljs-function"><span class="hljs-params">destination</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> { id, name, location } = destination;
    <span class="hljs-keyword">const</span> position = [location.latitude, location.longitude];
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Marker</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{id}</span> <span class="hljs-attr">position</span>=<span class="hljs-string">{position}</span> /&gt;</span></span>
  })}
&lt;/<span class="hljs-built_in">Map</span>&gt;
</code></pre>
<p>Here we:</p>
<ul>
<li>Loop through our <code>destinations</code> to dynamically create a new list of components inside our <code>&lt;Map&gt;</code></li>
<li>Inside each loop instance, we destructure our date from <code>destination</code></li>
<li>We create a new <code>position</code> array with the latitude and longitude</li>
<li>Create a new <code>Marker</code> where we use our position to add it to the map</li>
</ul>
<p>This gives us our markers on the map!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/mapping-app-with-destination-markers.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Markers for each destination in the mapping app</em></p>
<p>But we want to know what each of those locations are, so let’s also add a popup to each marker that will show the name.</p>
<p>First, we need to import <code>Popup</code> from <code>react-leaflet</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Marker, Popup } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-leaflet'</span>;
</code></pre>
<p>Then, let’s update our <code>&lt;Marker&gt;</code> component to return:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">return</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Marker</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{id}</span> <span class="hljs-attr">position</span>=<span class="hljs-string">{position}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Popup</span>&gt;</span>{ name }<span class="hljs-tag">&lt;/<span class="hljs-name">Popup</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">Marker</span>&gt;</span></span>
);
</code></pre>
<p>And once we save and open back up our map, you can now click on each marker and see our destinations name!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/mapping-app-with-destination-marker-popup.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Popup for each destination marker in the mapping app</em></p>
<h3 id="heading-before-were-done-center-the-map">Before we’re done, center the map</h3>
<p>Previously, our demo map centered on Washington, DC. Let’s update that to the center of the world since our map doesn’t focus on the United States.</p>
<p>Update the <code>LOCATION</code> variable to:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> LOCATION = {
  <span class="hljs-attr">lat</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">lng</span>: <span class="hljs-number">0</span>,
};
</code></pre>
<p>And with that, we have our map!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/mapping-app-with-travel-bucket-list-markers.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Final mapping app with markers and popups for each destination</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-travel-bucket-list/commit/56dbadb74cea2770174eb8ea7c039be27ca18971">Follow along with the commit!</a></p>
<h2 id="heading-what-else-other-features-can-we-add-to-our-app">What else other features can we add to our app?</h2>
<h3 id="heading-add-a-way-to-check-off-each-location">Add a way to check off each location</h3>
<p>Inside GraphCMS, you can add a new field to your Destination content model that allows you to select whether you visited each location or not.</p>
<p>With this value, we can add it to our query and update our map with some kind of indicator like a checkmark to show that we’ve checked it off our bucket list!</p>
<h3 id="heading-customize-your-map-background-styles">Customize your map background styles</h3>
<p>We’re using a public version of <a target="_blank" href="https://www.openstreetmap.org/#map=5/38.007/-95.844">OpenStreetMap</a> which is open source, but <a target="_blank" href="https://www.mapbox.com/">Mapbox</a> offers some cool maps we can use to make it look a little more impressive.</p>
<p>If you want to get started changing your map styles, you can <a target="_blank" href="https://www.freecodecamp.org/news/how-to-set-up-a-custom-mapbox-basemap-with-gatsby-and-react-leaflet/">check out this other walkthrough</a> of mine to learn how to use Mapbox.</p>
<p><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter">Check out the blog post</a> or <a target="_blank" href="https://www.youtube.com/watch?v=KcPJr1b_rv0">watch the video</a>!</p>
<h3 id="heading-style-the-map-markers-with-a-custom-image">Style the map markers with a custom image</h3>
<p>You can check out my video walk through on how to change the markers to a custom image.</p>
<p>Take that a step further and use the feature above to dynamically show a different marker image when you’ve checked off a location.</p>
<p><a target="_blank" href="https://egghead.io/lessons/react-customize-geojson-data-markers-with-a-react-leaflet-icon-image?pl=mapping-with-react-leaflet-e0e0&amp;af=atzgap">Check out the video on Egghead.io!</a></p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>Check out some of my other tutorials and videos:</p>
<ul>
<li><a target="_blank" href="https://egghead.io/playlists/mapping-with-react-leaflet-e0e0?af=atzgap">Mapping with React Leaflet</a> (<a target="_blank" href="https://egghead.io/?af=atzgap">egghead.io</a>)</li>
<li><a target="_blank" href="https://www.youtube.com/playlist?list=PLFsfg2xP7cbJTnTFH3OGXEAt9O1mpoqpR">Mapping Apps with React, Gatsby, &amp; Leaflet</a> (<a target="_blank" href="https://www.youtube.com/channel/UC7Wpv0Aft4NPNhHWW_JC4GQ">youtube.com</a>)</li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App with Gatsby and Leaflet</a> (colbyfayock.com)</li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a> (colbyfayock.com)</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a> (colbyfayock.com)</li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a> (colbyfayock.com)</li>
</ul>
<h2 id="heading-whats-on-your-travel-bucket-list">What’s on your travel bucket list?</h2>
<p><a target="_blank" href="https://twitter.com/colbyfayock">Let me know on Twitter!</a></p>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/colbyfayock/status/1275441134144110595"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></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>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to add Coronavirus (COVID-19) case statistics to your React map dashboard with Gatsby ]]>
                </title>
                <description>
                    <![CDATA[ Previously, we walked through creating a map that shows an interactive look at Coronavirus (COVID-19) cases per country. How can we extend this with some case statistics to show recent data about the impacts on our world? Author's note: Similar to be... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-coronavirus-covid-19-case-statistics-to-your-map-dashboard-in-gatsby-and-react-leaflet/</link>
                <guid isPermaLink="false">66bee8e6bc07dbcebef938dc</guid>
                
                    <category>
                        <![CDATA[ coronavirus ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analytics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 22 Apr 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-mapping-app-2600x1000.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Previously, we walked through creating a map that shows an interactive look at Coronavirus (COVID-19) cases per country. How can we extend this with some case statistics to show recent data about the impacts on our world?</p>
<p><em>Author's note: Similar to before, this dashboard is meant to be a demo and proof of concept for using real world data to build a dashboard. While this data should be accurate per the NovelCOVID API, I would recommend using tools like the <a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Johns Hopkins University dashboard</a> for complete and accurate analysis. Stay home and be safe! ❤️</em></p>
<ul>
<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-what-do-we-need-before-we-get-started">What do we need before we get started?</a></li>
<li><a class="post-section-overview" href="#heading-step-1-update-how-we-fetch-our-data-and-fetch-the-statistics">Step 1: Update how we fetch our data and fetch the statistics</a></li>
<li><a class="post-section-overview" href="#heading-step-2-adding-statistics-to-our-dashboard">Step 2: Adding statistics to our dashboard</a></li>
<li><a class="post-section-overview" href="#heading-step-3-make-the-data-human-friendly">Step 3: Make the data human friendly</a></li>
<li><a class="post-section-overview" href="#heading-step-4-add-the-last-updated-date">Step 4: Add the Last Updated date</a></li>
<li><a class="post-section-overview" href="#heading-what-can-i-do-next">What can I do next?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9bfxeod27fU" 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-we-going-to-build">What are we going to build?</h2>
<p>We're going to be extending our <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">original map demo</a> with some basic statistics that we can retrieve from the <a target="_blank" href="https://github.com/NovelCOVID/API">NovelCOVID API</a>. To get an idea, here's <a target="_blank" href="https://coronavirus-map-dashboard.netlify.app/">my demo</a> I'm basing this off of.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-covid-19-dashboard-map-stats.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus (COVID-19) map demo with dashboard statistics</em></p>
<p>While you're not required to have completed <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet/">Part 1</a> to apply these concepts, it definitely helps, and it lets you set up a map for your dashboard. If you'd like to start there, which I recommend, check out <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet/">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App with Gatsby and Leaflet</a> first.</p>
<h2 id="heading-woah-a-mapping-app">Woah, a mapping app?</h2>
<p>Yup. If you haven't played with maps before, don't be discouraged! It's not as bad as you probably think. If you'd rather start with mapping basics, you can  <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">read more about how mapping works</a>  first.</p>
<h2 id="heading-what-do-we-need-before-we-get-started">What do we need before we get started?</h2>
<p>For this walkthrough, you pretty much need a React app in some form. I'll be working with the dashboard we previously built in my last walkthrough that includes a <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet/">map of the cases of the Coronavirus (COVID-19) per country</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-map-tutorial-country-markers.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus (COVID-19) map dashboard</em></p>
<p>I recommend starting with the previous tutorial, but if you want to skip the map and start fresh, the easiest way would probably be to use <a target="_blank" href="https://github.com/facebook/create-react-app">Create React App</a>, <a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a>, or <a target="_blank" href="https://nextjs.org/">Next.js</a>.</p>
<h2 id="heading-step-1-update-how-we-fetch-our-data-and-fetch-the-statistics">Step 1: Update how we fetch our data and fetch the statistics</h2>
<p>To get started with our statistics dashboard, we're going to do a little prep work by changing how we're fetching the data. The goal here, is we're going to wrap our request logic in a reusable way so that we can use it for both our countries data and our new statistics data.</p>
<h3 id="heading-creating-a-new-react-hook-to-fetch-data">Creating a new React hook to fetch data</h3>
<p>Diving in, the first we'll do is create a new <a target="_blank" href="https://reactjs.org/docs/hooks-reference.html">React hook</a> that will serve as how we fetch the data. To get started, create a new file in your hooks directory called <code>useTracker.js</code>  and add a line inside of <code>hooks/index.js</code> to export it:</p>
<pre><code class="lang-js"><span class="hljs-comment">// New file src/hooks/useTracker.js</span>
<span class="hljs-comment">// This will be empty for now</span>
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// Inside hooks/index.js</span>
<span class="hljs-keyword">export</span> { <span class="hljs-keyword">default</span> <span class="hljs-keyword">as</span> useTracker } <span class="hljs-keyword">from</span> <span class="hljs-string">'./useTracker'</span>;
</code></pre>
<p>Inside of our <code>useTracker.js</code> file, we're going to set up our request logic. This is a long file, so make sure you copy and paste the entire thing before we walk through what it does:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">const</span> API_HOST = <span class="hljs-string">'https://corona.lmao.ninja/v2'</span>;

<span class="hljs-keyword">const</span> ENDPOINTS = [
  {
    <span class="hljs-attr">id</span>: <span class="hljs-string">'all'</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">'/all'</span>,
    <span class="hljs-attr">isDefault</span>: <span class="hljs-literal">true</span>
  },
  {
    <span class="hljs-attr">id</span>: <span class="hljs-string">'countries'</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">'/countries'</span>
  }
]

<span class="hljs-keyword">const</span> defaultState = {
  <span class="hljs-attr">data</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">state</span>: <span class="hljs-string">'ready'</span>
}

<span class="hljs-keyword">const</span> useTracker = <span class="hljs-function">(<span class="hljs-params">{ api = <span class="hljs-string">'all'</span> }</span>) =&gt;</span> {

  <span class="hljs-keyword">const</span> [tracker = {}, updateTracker] = useState(defaultState)

  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchTracker</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> route = ENDPOINTS.find(<span class="hljs-function">(<span class="hljs-params">{ id } = {}</span>) =&gt;</span> id === api);

    <span class="hljs-keyword">if</span> ( !route ) {
      route = ENDPOINTS.find(<span class="hljs-function">(<span class="hljs-params">{ isDefault } = {}</span>) =&gt;</span> !!isDefault);
    }

    <span class="hljs-keyword">let</span> response;

    <span class="hljs-keyword">try</span> {
      updateTracker(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> {
          ...prev,
          <span class="hljs-attr">state</span>: <span class="hljs-string">'loading'</span>
        }
      });
      response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">`<span class="hljs-subst">${API_HOST}</span><span class="hljs-subst">${route.path}</span>`</span>);
    } <span class="hljs-keyword">catch</span>(e) {
      updateTracker(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> {
          ...prev,
          <span class="hljs-attr">state</span>: <span class="hljs-string">'error'</span>,
          <span class="hljs-attr">error</span>: e
        }
      });
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> { data } = response;

    updateTracker(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> {
      <span class="hljs-keyword">return</span> {
        ...prev,
        <span class="hljs-attr">state</span>: <span class="hljs-string">'ready'</span>,
        data
      }
    });

  }

  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetchTracker()
  }, [api])

  <span class="hljs-keyword">return</span> {
    fetchTracker,
    ...tracker
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useTracker;
</code></pre>
<p>Starting from the top:</p>
<ul>
<li>We import our dependencies: we're going to use Reacts <code>useEffect</code>  and <code>useState</code> hooks to manage our requests</li>
<li>We define default constants: we have a base API endpoint for our data, a list of the available endpoints we'll use, and a state object that will store our data</li>
<li>We define our <code>useTracker</code> hook:  our hook includes one argument <code>api</code>  that will allow us to specify which endpoint we'll use to make our request</li>
<li>We set up a state instance: we'll want to keep track of our fetched data, so we create a <code>tracker</code> state instance that we'll be able to update</li>
<li>We created an asynchronous <code>fetchTracker</code> function: we'll use this to make our actual request</li>
<li>Inside our function: we first find the API route and create our URL, update our state instance to a "loading" state, try to make our request, catch any errors if there are any, and finally if the request is successful, we update our state with that data</li>
<li>We trigger our function: using a <code>useEffect</code> hook, we trigger our <code>fetchTracker</code> function to make the request. We only have one dependency of <code>api</code>. This means the function will only fire the first time and any time the <code>api</code> value we pass in changes. We won't be changing that value, but it may be helpful in other instances if you're dynamically changing the API used</li>
<li>We return our tracker: the returned object includes both our <code>tracker</code> data as well as our <code>fetchTracker</code> function that we could use to refetch the data if we'd like</li>
</ul>
<p>And with all of that, we have a brand new hook that will fetch data from the NovelCOVID API.</p>
<h3 id="heading-using-our-new-tracker-hook">Using our new tracker hook</h3>
<p>To make use of this hook, let's jump over to <code>src/pages/index.js</code>, remove our <code>axios</code> import if it's there, and instead import our hook:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useTracker } <span class="hljs-keyword">from</span> <span class="hljs-string">'hooks'</span>;
</code></pre>
<p>With our hook, let's replace our original country data request.  First, add the following to the top of the <code>IndexPage</code> component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: countries = [] } = useTracker({
  <span class="hljs-attr">api</span>: <span class="hljs-string">'countries'</span>
});

<span class="hljs-keyword">const</span> hasCountries = <span class="hljs-built_in">Array</span>.isArray(countries) &amp;&amp; countries.length &gt; <span class="hljs-number">0</span>;
</code></pre>
<p>This will let us fetch our country data and let us know if we have any results. Next, let's replace our original request.</p>
<p>Inside of our <code>mapEffect</code> function, let's remove the <code>axios</code> request in addition to the response, the destructured data object, and the <code>hasData</code> constant.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/code-diff-map-effect-countries-data.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Code diff showing update to map effect</em></p>
<p>Then, replace <code>hasData</code> with <code>hasCountries</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> ( !hasCountries ) <span class="hljs-keyword">return</span>;
</code></pre>
<p>And replace <code>data</code> with <code>countries</code> in the <code>geoJson</code> object where we map our features:</p>
<pre><code class="lang-js">features: countries.map(<span class="hljs-function">(<span class="hljs-params">country = {}</span>) =&gt;</span> {
</code></pre>
<p>At this point, if you hit save and refresh, you shouldn't notice any difference to what you previously had.</p>
<h3 id="heading-add-a-request-for-our-stats">Add a request for our stats</h3>
<p>Now that we are using our <code>useTracker</code> hook to fetch our country data, let's also use that to fetch our stats.</p>
<p>Right next to where we set up our <code>useTracker</code> hook before, let's add another request:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: stats = {} } = useTracker({
  <span class="hljs-attr">api</span>: <span class="hljs-string">'all'</span>
});
</code></pre>
<p>And if we add a <code>console.log</code> statement under to see what's inside <code>stats</code>:</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'stats'</span>, stats);
</code></pre>
<p>We should see our <code>stats</code> data object logged out!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/console-log-coronavirus-stats-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Using console.log to show Coronavirus (COVID-19) statistics</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/fe9d85e57f7474a86d38213676bf62df4b6168a4">Follow along with the commit!</a></p>
<h2 id="heading-step-2-adding-statistics-to-our-dashboard">Step 2: Adding statistics to our dashboard</h2>
<p>Now that we have our data available to use, let's use it!</p>
<p>To get started adding our statistics to the dashboard, let's create a data structure that will allow us to easily configure the data we want to use.</p>
<p>To do this, let's first create a new array called <code>dashboardStats</code> below <code>hasCountries</code> at the top of the page component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> dashboardStats = [];
</code></pre>
<p>Inside this array, let's add some new objects that specify our data that we're pulling from the <code>stats</code> object we requested. To start, let's try to add:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> dashboardStats = [
  {
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Total Cases'</span>,
      <span class="hljs-attr">value</span>: stats?.cases
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Per 1 Million'</span>,
      <span class="hljs-attr">value</span>: stats?.casesPerOneMillion
    }
  },
  {
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Total Deaths'</span>,
      <span class="hljs-attr">value</span>: stats?.deaths
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Per 1 Million'</span>,
      <span class="hljs-attr">value</span>: stats?.deathsPerOneMillion
    }
  },
  {
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Total Tests'</span>,
      <span class="hljs-attr">value</span>: stats?.tests
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Per 1 Million'</span>,
      <span class="hljs-attr">value</span>: stats?.testsPerOneMillion
    }
  }
]
</code></pre>
<p>The reason we're splitting this up into <code>primary</code> and <code>secondary</code> keys, is we're going to use that to differentiate between logically similar stats that we want to style a little bit differently.</p>
<p>_Note: if you're not familiar with the <code>?.</code> syntax, it's called <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining">Optional Chaining</a>. This allows us to chain our properties without worrying about if the objects exist. If <code>stats</code> is undefined, it will simply return undefined instead of throwing an error._</p>
<p>With our stats data, let's add the tracker to our map. Let's remove our current <code>&lt;Map&gt;</code> component and include it nested inside our tracker div in the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"tracker"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Map</span> {<span class="hljs-attr">...mapSettings</span>} /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stats"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      { dashboardStats.map(({ primary = {}, secondary = {} }, i) =&gt; {
        return (
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">Stat-</span>${<span class="hljs-attr">i</span>}`} <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stat"</span>&gt;</span>
            { primary.value &amp;&amp; (
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stat-primary"</span>&gt;</span>
                { primary.value }
                <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{ primary.label }<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            )}
            { secondary.value &amp;&amp; (
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stat-secondary"</span>&gt;</span>
                { secondary.value }
                <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{ secondary.label }<span class="hljs-tag">&lt;/<span class="hljs-name">strong</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">li</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">div</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>This code should be immediately following the <code>&lt;Helmet&gt;</code> component if you're following along.</p>
<p>To explain what we're doing:</p>
<ul>
<li>We're creating a "tracker" div that will organize our stats</li>
<li>We move our <code>&lt;Map</code> component inside of this tracker</li>
<li>We create a separate section called "tracker-stats"</li>
<li>Inside of this, we create an unordered list (<code>ul</code>)</li>
<li>Inside of our list, we loop through all of our stats inside <code>dashboardStats</code></li>
<li>For each stat, we create a new list element (<code>li</code>) and include 2 optional paragraphs that includes our primary stat data and our secondary stat data</li>
</ul>
<p>Once we reload our page, we should now see a few stats:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/adding-coronavirus-stats-to-page.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding the first statistics to the page</em></p>
<p>Now that we have our stats on our page, let's make them look like they're in a dashboard.</p>
<p>Let's create a new file called <code>_tracker.scss</code> inside of our <code>src/assets/stylesheets/components</code> directory. Once that file is created, additionally add it to the <code>src/assets/stylesheets/components/__components.scss</code> file:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@import</span> <span class="hljs-string">"tracker"</span>;
</code></pre>
<p>With our new component style file ready to go, let's add some styles into <code>_tracker.scss</code>:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.tracker-stats</span> {

  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
  <span class="hljs-attribute">border-top</span>: solid <span class="hljs-number">1px</span> darken(<span class="hljs-variable">$blue-grey-900</span>, <span class="hljs-number">5</span>);

  <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">display</span>: grid;
    grid-template-<span class="hljs-attribute">columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr;
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  }

}

<span class="hljs-selector-class">.tracker-stat</span> {

  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2em</span>;
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">padding</span>: .<span class="hljs-number">5em</span>;
  <span class="hljs-attribute">border-right</span>: solid <span class="hljs-number">1px</span> darken(<span class="hljs-variable">$blue-grey-900</span>, <span class="hljs-number">5</span>);
  <span class="hljs-attribute">border-bottom</span>: solid <span class="hljs-number">1px</span> darken(<span class="hljs-variable">$blue-grey-900</span>, <span class="hljs-number">5</span>);

  <span class="hljs-selector-tag">strong</span> {
    <span class="hljs-attribute">font-weight</span>: normal;
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$blue-grey-300</span>;
  }

}

<span class="hljs-selector-class">.tracker-stat-primary</span> {

  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;

  <span class="hljs-selector-tag">strong</span> {
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">5em</span>;
  }

}

<span class="hljs-selector-class">.tracker-stat-secondary</span> {

  <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">5em</span>;
  <span class="hljs-attribute">margin</span>: .<span class="hljs-number">8em</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>;

  <span class="hljs-selector-tag">strong</span> {
    <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">8em</span>;
    <span class="hljs-attribute">margin-left</span>: .<span class="hljs-number">4em</span>;
  }

}
</code></pre>
<p>Above – we're adding colors and organizational effects, such as using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout">CSS Grid</a>, to allow our data to be organized in an easy to read way and to look good! We're also making use of some pre-existing colors variables that are used within the project to keep the color use consistent.</p>
<p>Once you save those styles and reload the page, it should look much better:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/adding-coronavirus-case-statistics-to-map-dashboard.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding case statistics to the dashboard</em></p>
<p>From here, feel free to add more stats or adjust them to your liking. In the demo I created, I added the stats for active cases, critical cases, and recovered cases. If you'd like to do the same, you can <a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/eb8a28c9e46dc2327ada0df21b250422e55d304c">check out the commit</a>.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/eb8a28c9e46dc2327ada0df21b250422e55d304c">Follow along with the commit!</a></p>
<h2 id="heading-step-3-make-the-data-human-friendly">Step 3: Make the data human friendly</h2>
<p>Now the rest of this walkthrough could be considered optional, but ultimately we want people to be able to read these statistics, right? So let's make the numbers a little more easy to read.</p>
<p>First, let's open our <code>src/lib/util.js</code> file and add this function:</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * commafy
 * <span class="hljs-doctag">@description </span>Applies appropriate commas to large numbers
 */</span>

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">commafy</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">let</span> numberString = <span class="hljs-string">`<span class="hljs-subst">${value}</span>`</span>;

  numberString = numberString.split(<span class="hljs-string">''</span>);

  numberString.reverse();

  numberString = numberString.reduce(<span class="hljs-function">(<span class="hljs-params">prev, current, index</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> shouldComma = (index + <span class="hljs-number">1</span>) % <span class="hljs-number">3</span> === <span class="hljs-number">0</span> &amp;&amp; index + <span class="hljs-number">1</span> &lt; numberString.length;
    <span class="hljs-keyword">let</span> updatedValue = <span class="hljs-string">`<span class="hljs-subst">${prev}</span><span class="hljs-subst">${current}</span>`</span>;
    <span class="hljs-keyword">if</span> ( shouldComma ) {
      updatedValue = <span class="hljs-string">`<span class="hljs-subst">${updatedValue}</span>,`</span>;
    }
    <span class="hljs-keyword">return</span> updatedValue;
  }, <span class="hljs-string">''</span>);

  numberString = numberString.split(<span class="hljs-string">''</span>);
  numberString.reverse()
  numberString = numberString.join(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">return</span> numberString;
}
</code></pre>
<p>This function will take a number and turn it into a string with commas. To walk through what it does:</p>
<ul>
<li>Takes in a value as an argument. For our use, this value will most likely be a number.</li>
<li>It converts the value into a string. We'll use this to work with adding commas to our number.</li>
<li>We split that string into an array and reverse it. We want to reverse it because it makes it easier to add our commas depending on the index.</li>
<li>We use the javascript <code>reduce</code> function to recreate our number-string. After every 3 numbers, we want to add a comma.</li>
<li>Once we have our new value with the commas, we want to re-reverse it. So we split it again, reverse the array of characters, and re-join it, which is what we return</li>
</ul>
<p>And now that we have our <code>commafy</code> function, let's use it. Back inside <code>src/pages/index.js</code>, let's import our function at the top of the page:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { commafy } <span class="hljs-keyword">from</span> <span class="hljs-string">'lib/util'</span>;
</code></pre>
<p>Then, in our <code>dashboardStats</code> array, let's replace every number value with a ternary expression and function that will convert our number if it's available:</p>
<pre><code class="lang-js">value: stats ? commafy(stats?.cases) : <span class="hljs-string">'-'</span>
</code></pre>
<p>This line checks to see if <code>stats</code> exists. If it does, we <code>commafy</code> the <code>cases</code> value. If it doesn't exist, we return a <code>-</code> to show it's unavailable.</p>
<p>Once we repeat that process for all of our numbers, we can save, reload the page, and see our human friendly numbers!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-dashboard-stats-with-readable-stats.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Formatting the statistics to be human readable</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/90f266c17815239d9d3356d9b9d660915fdc26c2">Follow along with the commit!</a></p>
<h2 id="heading-step-4-add-the-last-updated-date">Step 4: Add the Last Updated date</h2>
<p>Finally, we want to make sure people are staying informed and understand the last time this data was updated. Luckily, our API provides a Last Updated date for us, so let's use it!</p>
<p>At the bottom of our "tracker" <code>div</code> under <code>tracker-stats</code>, let's add the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"tracker-last-updated"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
    Last Updated: { stats?.updated }
  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>This creates a new section where we simply include the <code>updated</code> property from our stats. And if we save and reload the page, we can see the last updated date!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronvirus-dashboard-last-updated.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding last updated to the dashboard</em></p>
<p>But how could we even understand what that number is, unless you're the computer crawling this blog post? So let's change it to a human readable format like we did with our numbers.</p>
<p>Inside of our <code>src/lib/util.js</code> file, let's add another function:</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * friendlyDate
 * <span class="hljs-doctag">@description </span>Takes in a date value and returns a friendly version
 */</span>

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">friendlyDate</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(value);
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat(<span class="hljs-string">'en'</span>, {
    <span class="hljs-attr">year</span>: <span class="hljs-string">'numeric'</span>,
    <span class="hljs-attr">month</span>: <span class="hljs-string">'short'</span>,
    <span class="hljs-attr">day</span>: <span class="hljs-string">'2-digit'</span>,
    <span class="hljs-attr">hour</span>: <span class="hljs-string">'numeric'</span>,
    <span class="hljs-attr">minute</span>: <span class="hljs-string">'numeric'</span>
  }).format(date);
}
</code></pre>
<p>This function creates a new <code>Date</code> object, then uses the javascript <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat">International DateTimeFormat API</a> to convert it into a friendly readable format!</p>
<p>Once that's saved, let's import it next to our <code>commafy</code> function at the top of <code>src/pages/index.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { commafy, friendlyDate } <span class="hljs-keyword">from</span> <span class="hljs-string">'lib/util'</span>;
</code></pre>
<p>Then we can update our code similar to how we updated our numbers:</p>
<pre><code class="lang-jsx">Last Updated: { stats ? friendlyDate(stats?.updated) : <span class="hljs-string">'-'</span> }
</code></pre>
<p>And if we save and reload, we see it in a human readable way!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronvirus-dashboard-last-updated-formatted-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Formatting the last updated date</em></p>
<p>Finally for our "last updated" should look like it fits in with the rest of the dashboard, so let's add a few more styles. Inside of our <code>_tracker.scss</code> file we were working with earlier:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.tracker-last-updated</span> {

  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
  <span class="hljs-attribute">padding</span>: .<span class="hljs-number">8em</span> <span class="hljs-number">0</span>;

  <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$blue-grey-300</span>;
    <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">8em</span>;
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  }

}
</code></pre>
<p>And once we hit save and refresh the browser, we have our dashboard statistics with the last updated time! ?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-dashboard-formatted-styled.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Final dashboard with formatted lasted updated date</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/408286aecb32223c8782eb1539f5563135c75dfb">Follow along with the commit!</a></p>
<h2 id="heading-what-can-i-do-next">What can I do next?</h2>
<h3 id="heading-make-the-marker-tooltip-data-human-friendly">Make the marker tooltip data human friendly</h3>
<p>Now that we have our handy <code>commafy</code> and <code>friendlyDate</code> functions, we can reuse those functions to clean up the data in our country marker popups!</p>
<h3 id="heading-use-the-fetchtracker-function-to-poll-for-updates">Use the fetchTracker function to poll for updates</h3>
<p>Inside of the <code>useTracker</code> hook we created, we exported a function called <code>fetchTracker</code>. This allows us to force a request to the API to fetch new data. To make sure our map stays current even when somebody doesn't refresh the page, we can create a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">timer</a> in javascript to regularly invoke that function to update our dashboard data.</p>
<h3 id="heading-clear-the-map-layers-before-re-adding-the-new-ones">Clear the map layers before re-adding the new ones</h3>
<p>One thing we're currently not doing is cleaning up old layers before adding a new one. The way the map is set up, it just keeps layering them on top. What we can do is before we add all of our new layers, we can clear out the old ones. <a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/cad3b5a6e31a6ae090549c12e40a08fee4db4aa5">Check out this commit</a> to get started!</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App in React with Gatsby and Leaflet</a> (Part 1 of this post)</li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter/">How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<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>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter ]]>
                </title>
                <description>
                    <![CDATA[ Building maps can be pretty powerful, but often you’re stuck with open source options for the map imagery that might not help the readability of your data. How can we leverage Mapbox’s tile APIs to add a custom basemap to our React Leaflet app? What... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-set-up-a-custom-mapbox-basemap-with-gatsby-and-react-leaflet/</link>
                <guid isPermaLink="false">66b8e36647c23b7ae1ad0bdb</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mapbox ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 08 Apr 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-basemap-react-leaflet-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Building maps can be pretty powerful, but often you’re stuck with open source options for the map imagery that might not help the readability of your data. How can we leverage Mapbox’s tile APIs to add a custom basemap to our React Leaflet app?</p>
<ul>
<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-what-is-mapbox">What is Mapbox?</a></li>
<li><a class="post-section-overview" href="#heading-part-1-creating-a-custom-mapbox-style">Part 1: Creating a custom Mapbox style</a></li>
<li><a class="post-section-overview" href="#heading-part-2-adding-a-custom-tilelayer-to-react-leaflet">Part 2: Adding a custom TileLayer to React Leaflet</a></li>
<li><a class="post-section-overview" href="#heading-part-3-adding-a-custom-basemap-to-gatsby-starter-leaflet">Part 3: Adding a custom basemap to Gatsby Starter Leaflet</a></li>
<li><a class="post-section-overview" href="#heading-securing-your-mapbox-key">Securing your Mapbox key</a></li>
<li><a class="post-section-overview" href="#heading-want-to-learn-more-about-maps">Want to learn more about maps?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/KcPJr1b_rv0" 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-we-going-to-build">What are we going to build?</h2>
<p>We’re going to walk through creating a new basic <a target="_blank" href="https://www.mapbox.com/mapbox-studio/">Mapbox style</a> in our <a target="_blank" href="https://www.mapbox.com/">Mapbox</a> account. Once created, we’re going to use their <a target="_blank" href="https://docs.mapbox.com/api/maps/">Map API</a> to add a custom basemap to our <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a> app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/gatsby-starter-leaflet-with-mapbox-tilelayer.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Gatsby Starter Leaflet with Mapbox basemap</em></p>
<p>For our map, we’re going to use this <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a> I created that will allow you to easily spin up a new mapping app. Before we spin that up though, I’ll walk you through how to add it using only React Leaflet components.</p>
<h2 id="heading-a-mapping-app">A mapping app?</h2>
<p>Yup! Maps are used all around the world to study datasets for geographic locations. They're important tools for scientists and others that are trying to help the world.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-map-dashboard-demo.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus (COVID-19) custom map</em></p>
<p>If you want to learn more about building a map and adding data to it, you can check out some of <a target="_blank" href="https://www.freecodecamp.org/news/author/colbyfayock/">my other articles</a> first such as creating a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-coronavirus-covid-19-dashboard-map-app-in-react-with-gatsby-and-leaflet/">Coronavirus (COVID-19) map</a> or a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet/">Summer Road Trip map</a> as well as a little bit of inspiration about why <a target="_blank" href="https://www.freecodecamp.org/news/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping/">Anyone Can Map</a>.</p>
<h2 id="heading-what-is-mapbox">What is Mapbox?</h2>
<p>Mapbox is a mapping platform that allows its customers to create custom mapping solutions. They also leverage a variety of APIs that provide powerful capabilities for building map features.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-homepage.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.mapbox.com/">mapbox.com</a></em></p>
<p>For our purposes, we’re going to utilize their Map API, specifically their Static Tiles API, to serve a custom map style that we create.</p>
<h2 id="heading-part-1-creating-a-custom-mapbox-style">Part 1: Creating a custom Mapbox style</h2>
<p>To get the look and feel that we want for our map, it’s important to have a basemap that helps make our data present itself without distractions. Plus, sometimes it’s fun to have a custom map.</p>
<h3 id="heading-mapbox-account">Mapbox account</h3>
<p>The first thing we’ll need to set up our custom Mapbox style is to have an account. I'm not going to walk you through that process, but you can head over to <a target="_blank" href="https://www.mapbox.com/">Mapbox’s website</a> where you can sign up for free: <a target="_blank" href="https://www.mapbox.com/">mapbox.com</a></p>
<h3 id="heading-creating-a-new-custom-style">Creating a new custom style</h3>
<p>Creating a new style in Mapbox isn’t as hard as it sounds. While it can get really complex if you want something unique, we can copy one of Mapbox’s default styles to get started.</p>
<p>First, head over to Mapbox’s <a target="_blank" href="https://studio.mapbox.com/">Studio dashboard</a> by clicking your account link in the top right corner when logged in.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapbox Studio</em></p>
<p>Once we’re on our Studio dashboard, we want to select the New Style button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio-new-style.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new style in Mapbox Studio</em></p>
<p>After clicking the button, a modal will pop up allowing you to choose a template. You can choose whatever you want here, but I’m going to choose Monochrome with a variation of Dark. And after you’ve selected your template, click the Customize button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio-new-style-choose-template.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Select and customize a template for a new style in Mapbox Studio</em></p>
<p>And now we’re dropped into our customization UI.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-customize-style.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapbox customize style UI</em></p>
<p>From here, you can really do what you’d like. There are a ton of options to customize your map. It’s a little complex to try to dig in here, but <a target="_blank" href="https://docs.mapbox.com/studio-manual/overview/">Mapbox provides some resources</a> to try to help you get productive.</p>
<h3 id="heading-generating-a-mapbox-token">Generating a Mapbox token</h3>
<p>Once you’re happy with your new style and everything’s published, we want to generate a token that we’ll use for providing access to our Map.</p>
<p>Head on over to the Account section of the Mapbox dashboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-account.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new token in Mapbox</em></p>
<p>Mapbox provides you with a “default” token that you can use in your applications. You're free to use this, but I recommend creating a new token that you can provide a unique name, that way if you ever blow past the <a target="_blank" href="https://www.mapbox.com/pricing/">free tier</a> of Mapbox, you’ll be able to track your usage.</p>
<p>Additionally, it’s best to keep a separate token for each application, that way you can easily rotate an individual key, without having to update every application using it.</p>
<p>Once you click Create a token, you can set up the key how you’d like, with the scopes and permissions you choose, but for our purposes, you can leave all of the Public scopes checked for our map, which they do by default.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-create-token.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new access token in Mapbox</em></p>
<h3 id="heading-configuring-our-custom-endpoint">Configuring our custom endpoint</h3>
<p>For this tutorial, we’re going to use <a target="_blank" href="https://docs.mapbox.com/api/maps/#static-tiles">Mapbox’s Static Tiles service</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-static-tiles-map-api.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapbox Static Tiles Maps API</em></p>
<p>Our endpoint will look like the following:</p>
<pre><code>https:<span class="hljs-comment">//api.mapbox.com/styles/v1/{username}/{style_id}/tiles/256/{z}/{x}/{y}@2x?access_token={access_token}</span>
</code></pre><p>There are a few parameters here we need to understand:</p>
<ul>
<li>username: this will be your Mapbox account’s username</li>
<li>style_id: this will be the ID of the style you created before</li>
<li>z, x, y: these are parameters that Leaflet programmatically swaps out, so we want to leave them as is</li>
<li>access_token: this is the Mapbox key you created above</li>
</ul>
<p>To find your username and style ID, we can use the Style URL for our new Mapbox style to get those values.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio-style-url.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Finding the Style URL in Mapbox Studio</em></p>
<p>In my example, my Style URL looks like:</p>
<pre><code>mapbox:<span class="hljs-comment">//styles/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p</span>
</code></pre><p><code>colbyfayock</code> is my username and <code>ck8lryjfq0jdo1ip9ctmuhc6p</code> is my style ID.</p>
<p>And once I update my endpoint parameters, the final tilepoint URL will look like:</p>
<pre><code>https:<span class="hljs-comment">//api.mapbox.com/styles/v1/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p/tiles/256/{z}/{x}/{y}@2x?access_token=MYACCESSTOKEN</span>
</code></pre><h2 id="heading-part-2-adding-a-custom-tilelayer-to-react-leaflet">Part 2: Adding a custom TileLayer to React Leaflet</h2>
<p>When building a map with React Leaflet, your main component will be a <code>&lt;Map&gt;</code> that wraps the entirety of the app. This is what sets up your <a target="_blank" href="https://leafletjs.com/reference-1.6.0.html#map-example">Map instance</a> for <a target="_blank" href="https://leafletjs.com/">Leaflet</a>.</p>
<p>For our purposes here, we’re going to use the example on the <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet homepage</a> as our starting point.</p>
<h3 id="heading-react-leaflet-tilelayer-component">React Leaflet TileLayer Component</h3>
<p>Inside of your <code>&lt;Map&gt;</code> component you include a <code>&lt;TileLayer&gt;</code> component, which defines the imagery of the world that you base your map upon.</p>
<p>The example on the React Leaflet homepage uses a public version of <a target="_blank" href="https://www.openstreetmap.org/">OpenStreetMap</a> as their TileLayer, which is an open source map project created and updated by people all around the world.</p>
<pre><code class="lang-react">&lt;Map center={position} zoom={13}&gt;
  &lt;TileLayer
    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    attribution="&amp;copy; &lt;a href=&amp;quot;http://osm.org/copyright&amp;quot;&gt;OpenStreetMap&lt;/a&gt; contributors"
  /&gt;
&lt;/Map&gt;
</code></pre>
<p>This gives you a basic map, but we want to swap in Mapbox so we can set up a custom look and feel for our map.</p>
<h3 id="heading-custom-mapbox-tilelayer">Custom Mapbox TileLayer</h3>
<p>To add our custom style, we’ll want to update the <code>url</code> and <code>attribution</code> props of the <code>TileLayer</code> component.</p>
<p>For URL, it will simply be the custom style endpoint we created earlier, so in my example, it looks like:</p>
<pre><code>https:<span class="hljs-comment">//api.mapbox.com/styles/v1/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p/tiles/256/{z}/{x}/{y}@2x?access_token=MYACCESSTOKEN</span>
</code></pre><p>For attribution, we want to credit Mapbox as the service, so we want to set our attribution as:</p>
<pre><code><span class="hljs-built_in">Map</span> data &amp;copy; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&amp;quot;https://www.openstreetmap.org/&amp;quot;</span>&gt;</span>OpenStreetMap<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span> contributors, <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&amp;quot;https://creativecommons.org/licenses/by-sa/2.0/&amp;quot;</span>&gt;</span>CC-BY-SA<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>, Imagery &amp;copy; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&amp;quot;https://www.mapbox.com/&amp;quot;</span>&gt;</span>Mapbox<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>
</code></pre><p>When plugged in to our <code>TileLayer</code>, our code should now look like this:</p>
<pre><code class="lang-react">&lt;Map center={position} zoom={13}&gt;
  &lt;TileLayer
    url="https://api.mapbox.com/styles/v1/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p/tiles/256/{z}/{x}/{y}@2x?access_token=MYACCESSTOKEN"
    attribution="Map data &amp;copy; &lt;a href=&amp;quot;https://www.openstreetmap.org/&amp;quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&amp;quot;https://creativecommons.org/licenses/by-sa/2.0/&amp;quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery &amp;copy; &lt;a href=&amp;quot;https://www.mapbox.com/&amp;quot;&gt;Mapbox&lt;/a&gt;"
  /&gt;
&lt;/Map&gt;
</code></pre>
<p>And once we open up our map, we should see our new basemap!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/react-leaflet-mapbox-basemap.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>React Leaflet with a Mapbox basemap</em></p>
<h3 id="heading-see-the-code">See the code!</h3>
<p>If you want to see how I did it, <a target="_blank" href="https://github.com/colbyfayock/my-mapbox-react-leaflet/commits/master">check out the diff commit by commit</a>.</p>
<p>The only caveat there is I created an <code>.env.development.local</code> file in the root of my project in which I stored a new environment variable called <code>REACT_APP_MAPBOX_KEY</code>  to store my Mapbox key.</p>
<h2 id="heading-part-3-adding-a-custom-basemap-to-gatsby-starter-leaflet">Part 3: Adding a custom basemap to Gatsby Starter Leaflet</h2>
<p>I’ve written <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">a few</a> <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">other</a> <a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping/">articles</a> on <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">how to get started</a> with my <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a>, but for this part, we’ll want to have a basic app spun up that we can use to change our <code>TileLayer</code> endpoint.</p>
<h3 id="heading-setting-up-our-react-leaflet-gatsby-app">Setting up our React Leaflet Gatsby app</h3>
<p>To get started, check out the instructions on the Starter github:</p>
<p><a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">https://github.com/colbyfayock/gatsby-starter-leaflet</a></p>
<p>Once you’re ready, you should have a basic mapping app ready to go!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/gatsby-starter-leaflet-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Leaflet Gatsby app in the browser</em></p>
<h3 id="heading-configuring-our-mapbox-service">Configuring our Mapbox service</h3>
<p>The first thing we’ll want to do is add Mapbox as a service in our <code>src/data/map-services.js</code> file.</p>
<p>Taking our custom endpoint URL that we created in Part 1, let’s set up a new object with a name of Mapbox, and with a url and attribution similar to what we did in Part 2.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> mapServices = [
  {
    <span class="hljs-attr">name</span>: ‘OpenStreetMap’,
    <span class="hljs-attr">attribution</span>: <span class="hljs-string">'&amp;copy; &lt;a href="http://osm.org/copyright”&gt;OpenStreetMap&lt;/a&gt; contributors’,
    url: ‘https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png’
  },
  {
    name: ‘Mapbox’,
    attribution: ‘Map data &amp;copy; &lt;a href=&amp;quot;https://www.openstreetmap.org/&amp;quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&amp;quot;https://creativecommons.org/licenses/by-sa/2.0/&amp;quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery &amp;copy; &lt;a href=&amp;quot;https://www.mapbox.com/&amp;quot;&gt;Mapbox&lt;/a&gt;’,
    url: `https://api.mapbox.com/styles/v1/colbyfayock/ck8c2foj72lqk1jnug0g2haw0/tiles/256/{z}/{x}/{y}@2x?access_token=MY_ACCESS_TOKEN`
  }
];</span>
</code></pre>
<h3 id="heading-using-our-mapbox-map-service">Using our Mapbox map service</h3>
<p>Once you have your Mapbox service set up, all that’s left is to open up the <code>src/pages/index.js</code> file, find the <code>mapSettings</code> object definition, and update the <code>defaultBaseMap</code> property to <code>Mapbox</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mapSettings = {
  <span class="hljs-attr">center</span>: CENTER,
  <span class="hljs-attr">defaultBaseMap</span>: ‘Mapbox’,
  <span class="hljs-attr">zoom</span>: DEFAULT_ZOOM,
  mapEffect
};
</code></pre>
<p>Save that change, refresh the map in your browser, and you should now see your custom basemap style!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/gatsby-starter-leaflet-with-mapbox-tilelayer-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Gatsby Starter Leaflet with custom Mapbox basemap in browser</em></p>
<h3 id="heading-see-the-code-1">See the code!</h3>
<p>If you want to see how I did it, <a target="_blank" href="https://github.com/colbyfayock/my-mapbox-gatsby-starter-leaflet/commit/9baa1b7003504dec5c938328ea9b54477f65ec58">check out the diff with the commit</a>.</p>
<p>The only caveat there is I created an <code>.env.development</code> file in the root of my project in which I stored a new environment variable called <code>GATSBY_MAPBOX_KEY</code>  to store my Mapbox key.</p>
<h2 id="heading-securing-your-mapbox-key">Securing your Mapbox key</h2>
<h3 id="heading-environment-variables">Environment variables</h3>
<p>Part of most development processes that use individual keys will generally set the keys up as environment variables. Environment variables are configured settings that don’t live in the code itself.</p>
<p>This is important because it prevents your key from being checked in to your code, which is bad from a security perspective, but it also allows you to provide a different key for different environments.</p>
<p>When generating your keys, try to keep this in mind, as it can save you in the long run.</p>
<h3 id="heading-locking-down-your-mapbox-key">Locking down your Mapbox key</h3>
<p>In your settings when creating a token or when editing a token, Mapbox allows you to specify only the URLs you want your key to be accessible from.</p>
<p>Though Mapbox has a generous free tier, you probably want to keep it locked down only to the URLs that you’re using it on. You can create multiple keys, where one could be for public use on your website and one would be for your local development.</p>
<p>This is helpful for instance, where you have a key that will never be used publicly for development purposes, but then you have a key that you deploy with, which can be locked down only to that URL.</p>
<p>If someone grabs your key, they could plug it into their own website and use up all of your free tier, potentially running up your bill!</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App in React with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<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>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to create a Coronavirus (COVID-19) Dashboard & Map App in React with Gatsby and Leaflet ]]>
                </title>
                <description>
                    <![CDATA[ The Coronavirus (COVID-19) pandemic has swiftly changed how all of us interact day to day. How can we use available APIs to build a mapping app that shows the impact it has had on the world? Update: The original NovelCOVID API v1 endpoint has been de... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-coronavirus-covid-19-dashboard-map-app-in-react-with-gatsby-and-leaflet/</link>
                <guid isPermaLink="false">66bee92588139a9746c0c5cc</guid>
                
                    <category>
                        <![CDATA[ coronavirus ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analytics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 31 Mar 2020 15:16:16 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/coronavirus-mapping-app.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The Coronavirus (COVID-19) pandemic has swiftly changed how all of us interact day to day. How can we use available APIs to build a mapping app that shows the impact it has had on the world?</p>
<p><strong>Update:</strong> The original NovelCOVID API v1 endpoint has been deprecated. Please update and use the following instead: <a target="_blank" href="https://corona.lmao.ninja/v2/countries">https://corona.lmao.ninja/v2/countries</a></p>
<p><em>Author’s Note: This is meant to be a demo and proof of concept for putting together an impactful mapping application using real life data. For complete and accurate analysis, please make sure to use tools like <a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Johns Hopkins University dashboard</a>. Stay home and be safe! ❤️</em></p>
<ul>
<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-what-do-we-need-before-we-get-started">What do we need before we get started?</a></li>
<li><a class="post-section-overview" href="#heading-step-1-cleaning-up-some-unneeded-code">Step 1: Cleaning up some unneeded code</a></li>
<li><a class="post-section-overview" href="#heading-step-2-fetching-the-coronavirus-data">Step 2: Fetching the Coronavirus data</a></li>
<li><a class="post-section-overview" href="#heading-step-3-transform-the-coronavirus-data-into-a-geographic-data-format">Step 3: Transform the Coronavirus data into a geographic data format</a></li>
<li><a class="post-section-overview" href="#heading-step-4-adding-the-coronavirus-data-to-the-map">Step 4: Adding the Coronavirus data to the map</a></li>
<li><a class="post-section-overview" href="#heading-what-else-can-we-do">What else can we do?</a></li>
<li><a class="post-section-overview" href="#heading-be-safe-and-stay-informed">Be safe and stay informed</a></li>
<li><a class="post-section-overview" href="#heading-want-to-learn-more-about-maps">Want to learn more about maps?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/GryBIsfBfro" 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-we-going-to-build">What are we going to build?</h2>
<p>We’ll be putting together a mapping application that uses an API containing recent Coronavirus statistics and maps out the locations and impact each country is facing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/coronavirus-map-dashboard-demo.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus map dashboard demo</em></p>
<p>On the map, we’ll show a marker for each country with the number of confirmed cases. On top of that, we’ll include a little popup tooltip that shows more in depth information.</p>
<p>The map we’ll build will mostly look like the above, but will look a little simpler. We’ll utilize the OpenStreetMap public tileserver instead of using a custom <a target="_blank" href="https://www.mapbox.com/">Mapbox</a></p>
<p>To get started, we’re going to use this <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a> I created to make the initial setup a little smoother. With our app bootstrapped, we’ll fetch our data and add markers to the map with our data.</p>
<h2 id="heading-woah-a-mapping-app">Woah, a mapping app?</h2>
<p>Yup. If you haven’t played with maps before, don’t be discouraged! It's not as bad as you probably think. If you’d rather start with mapping basics, you can <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">read more about how mapping works</a> first.</p>
<h2 id="heading-what-do-we-need-before-we-get-started">What do we need before we get started?</h2>
<p>If you followed along with my previous tutorials for <a target="_blank" href="https://www.freecodecamp.org/news/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">building a Santa Tracker</a> or <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet/">creating a Summer Road Trip map</a>, you can follow the same steps to get started. If not, we’ll want to make sure we have the following set up:</p>
<ul>
<li><a target="_blank" href="https://nodejs.org/en/">node</a> or <a target="_blank" href="https://yarnpkg.com/en/">yarn</a> - I'll be using yarn, but you can substitute with npm where appropriate</li>
<li><a target="_blank" href="https://www.gatsbyjs.org/docs/gatsby-cli/">Gatsby’s CLI</a> - <code>yarn global add gatsby-cli</code></li>
</ul>
<p>If you’re not sure about one of the above, you can try checking out the beginning <a target="_blank" href="https://www.freecodecamp.org/news/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">my previous tutorial</a>.</p>
<p>We’ll also want to set up a foundation for our map. We can do this by utilizing the Leaflet Gatsby Starter I put together that provides us a basic setup with <a target="_blank" href="https://leafletjs.com/">Leaflet</a> and <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a>.</p>
<pre><code class="lang-shell">gatsby new my-coronavirus-map https://github.com/colbyfayock/gatsby-starter-leaflet
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/terminal-creating-new-coronavirus-map-from-gatsby-starter.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new Leaflet Gatsby app in the terminal</em></p>
<p>After that’s finished running, you can navigate to the newly created project directory and start your local development server:</p>
<pre><code class="lang-shell">cd my-coronavirus-map
yarn develop
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/terminal-starting-gatsby-development-server-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Starting your Gatsby app in the terminal</em></p>
<p>If all goes as planned, your server should start and you should now be able to see your basic mapping app in your browser!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/gatsby-starter-leaflet-in-browser-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Leaflet Gatsby app in the browser</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commits/master">Follow along with the commit!</a></p>
<h2 id="heading-step-1-cleaning-up-some-unneeded-code">Step 1: Cleaning up some unneeded code</h2>
<p>The Gatsby Starter we're using to spin up this app comes with some demo code that we don’t need here. We’ll want to make all of the changes below in the file <code>src/pages/index.js</code>, which is the homepage of our app.</p>
<p>First, let’s remove everything from the <code>mapEffect</code> function. This function is used to run code that fires when the map renders.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// In src/pages/index.js</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement } = {}</span>) </span>{
  <span class="hljs-comment">// Get rid of everything in here</span>
}
</code></pre>
<p>We’ll also change the variable name of our <code>leafletElement</code> simply for being able to more easily understand the code as we write it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement: map } = {}</span>) </span>{
}
</code></pre>
<p>Next, we don’t want a marker this time, so let’s remove the <code>&lt;Marker</code> component from our <code>&lt;Map</code> component:</p>
<pre><code class="lang-react">&lt;Map {...mapSettings} /&gt;
</code></pre>
<p>Now that we have those pieces cleared out, we can remove all of the following imports and variables from the top of our file:</p>
<ul>
<li>useRef</li>
<li>Marker</li>
<li>promiseToFlyTo</li>
<li>getCurrentLocation</li>
<li>gatsby_astronaut</li>
<li>timeToZoom</li>
<li>timeToOpenPopupAfterZoom</li>
<li>timeToUpdatePopupAfterZoom</li>
<li>ZOOM</li>
<li>popupContentHello</li>
<li>popupContentGatsby</li>
<li>markerRef</li>
</ul>
<p>After, our map should still work, but not do anything.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/new-empty-mapping-app-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New mapping app with nothing going on</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/a3e9cff3949bb7ebb7cc89166c875e97b6dcb5a8">Follow along with the commit!</a></p>
<h2 id="heading-step-2-fetching-the-coronavirus-data">Step 2: Fetching the Coronavirus data</h2>
<p>For our app, we’re going to use the <a target="_blank" href="https://github.com/NovelCOVID/API">NovelCOVID API</a>. Particularly, we’re going to use the <a target="_blank" href="https://corona.lmao.ninja/countries">countries endpoint</a> to fetch the list of our countries and the stats associated with them.</p>
<p>For making requests, I personally like to use <a target="_blank" href="https://github.com/axios/axios">axios</a> as it has a nice to use API. If you want to use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">fetch</a> or your own favorite request library, substitute that in for this step.</p>
<p>We’ll start by installing axios:</p>
<pre><code class="lang-shell">yarn add axios
</code></pre>
<p>Once that installs, remember to restart your server.</p>
<p>Import the axios package ta the top of our <code>pages/index.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
</code></pre>
<p>Next we’ll actually make our request. Inside our <code>mapEffect</code> function, let’s try to make a request to the API endpoint:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement: map } = {}</span>) </span>{
    <span class="hljs-keyword">let</span> response;

    <span class="hljs-keyword">try</span> {
      response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://corona.lmao.ninja/v2/countries'</span>);
    } <span class="hljs-keyword">catch</span>(e) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Failed to fetch countries: <span class="hljs-subst">${e.message}</span>`</span>, e);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> { data = [] } = response;
}
</code></pre>
<p>In this snippet, we’re doing the following:</p>
<ul>
<li>Setting up a <code>response</code> variable that will allow us to store the response</li>
<li>Adding a <code>try/catch</code> block that will catch any API errors if the request fails</li>
<li>If the request is successful, we store the response in the <code>response</code> variable</li>
<li>If the request fails, we console log out the error and return out of the function so we don’t continue to run the code with a failed request</li>
<li>Once we have our response, we can destructure <code>data</code> from the response and set the default value to an empty array, as that will be the type of data we need</li>
</ul>
<p>After that’s set up, we can console log out the <code>data</code> object and we’ll see our data successfully fetched!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/coronavirus-location-data-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Logging the Coronavirus location data to the browser console</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/86bebfee4a34b9bad516879b228921cdaad55126">Follow along with the commit!</a></p>
<p><strong>Update:</strong> The previous commit includes a link to the original NovelCOVID v1 API endpoint which has now been deprecated. Please use this instead: <a target="_blank" href="https://corona.lmao.ninja/v2/countries">https://corona.lmao.ninja/v2/countries</a>.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/e8f63c7ca60ec358b2edc9bc3ed8935be85b5573">See updated commit</a>.</p>
<h2 id="heading-step-3-transform-the-coronavirus-data-into-a-geographic-data-format">Step 3: Transform the Coronavirus data into a geographic data format</h2>
<p>Now that we have our data, we can transform it into a geographic data format, particularly <a target="_blank" href="https://geojson.org/">GeoJSON</a>, that will allow us to interface with Leaflet.</p>
<p>Let’s start by adding this block of code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { data = [] } = response;
<span class="hljs-keyword">const</span> hasData = <span class="hljs-built_in">Array</span>.isArray(data) &amp;&amp; data.length &gt; <span class="hljs-number">0</span>;

<span class="hljs-keyword">if</span> ( !hasData ) <span class="hljs-keyword">return</span>;

<span class="hljs-keyword">const</span> geoJson = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'FeatureCollection'</span>,
  <span class="hljs-attr">features</span>: data.map(<span class="hljs-function">(<span class="hljs-params">country = {}</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { countryInfo = {} } = country;
    <span class="hljs-keyword">const</span> { lat, <span class="hljs-attr">long</span>: lng } = countryInfo;
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">type</span>: <span class="hljs-string">'Feature'</span>,
      <span class="hljs-attr">properties</span>: {
       ...country,
      },
      <span class="hljs-attr">geometry</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">'Point'</span>,
        <span class="hljs-attr">coordinates</span>: [ lng, lat ]
      }
    }
  })
}
</code></pre>
<p>So what are we doing here?</p>
<ul>
<li>We create a new constant called <code>hasData</code> that checks if our <code>data</code> variable is an array and has data</li>
<li>If we don’t have data, we want to return out of the function, as we don’t want to try to add data we don’t have</li>
<li>We create a <code>geoJson</code> object that will be our GeoJSON document</li>
<li>Our document is of type <code>FeatureCollection</code> and as our <code>features</code> we loop through our dataset</li>
<li>For each country in our data, we obtain the <code>lat</code> and <code>lng</code> to create a point for our map</li>
<li>We additionally add our country data as properties so we can access it within our mapping APIs</li>
</ul>
<p>If you <code>console.log</code> this object our into your browser and copy the contents, you can paste this into geojson.io and see the location data show up correctly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/location-data-geojson-io.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Previewing Coronavirus location data on geojson.io</em></p>
<p>With this GeoJSON document, we'll now be able to add it to our map.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/f0da2d05cbc16783322684da7a3efaa61022f5b6">Follow along with the commit!</a></p>
<h2 id="heading-step-4-adding-the-coronavirus-data-to-the-map">Step 4: Adding the Coronavirus data to the map</h2>
<p>We have our GeoJSON document with our location data, so let’s add it to the map.</p>
<p>Let’s start with this code block. It's a long one, but we’ll break it down piece by piece:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> geoJsonLayers = <span class="hljs-keyword">new</span> L.GeoJSON(geoJson, {
  <span class="hljs-attr">pointToLayer</span>: <span class="hljs-function">(<span class="hljs-params">feature = {}, latlng</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { properties = {} } = feature;
    <span class="hljs-keyword">let</span> updatedFormatted;
    <span class="hljs-keyword">let</span> casesString;

    <span class="hljs-keyword">const</span> {
      country,
      updated,
      cases,
      deaths,
      recovered
    } = properties

    casesString = <span class="hljs-string">`<span class="hljs-subst">${cases}</span>`</span>;

    <span class="hljs-keyword">if</span> ( cases &gt; <span class="hljs-number">1000</span> ) {
      casesString = <span class="hljs-string">`<span class="hljs-subst">${casesString.slice(<span class="hljs-number">0</span>, <span class="hljs-number">-3</span>)}</span>k+`</span>
    }

    <span class="hljs-keyword">if</span> ( updated ) {
      updatedFormatted = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(updated).toLocaleString();
    }

    <span class="hljs-keyword">const</span> html = <span class="hljs-string">`
      &lt;span class="icon-marker"&gt;
        &lt;span class="icon-marker-tooltip"&gt;
          &lt;h2&gt;<span class="hljs-subst">${country}</span>&lt;/h2&gt;
          &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;Confirmed:&lt;/strong&gt; <span class="hljs-subst">${cases}</span>&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Deaths:&lt;/strong&gt; <span class="hljs-subst">${deaths}</span>&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Recovered:&lt;/strong&gt; <span class="hljs-subst">${recovered}</span>&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Last Update:&lt;/strong&gt; <span class="hljs-subst">${updatedFormatted}</span>&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/span&gt;
        <span class="hljs-subst">${ casesString }</span>
      &lt;/span&gt;
    `</span>;

    <span class="hljs-keyword">return</span> L.marker( latlng, {
      <span class="hljs-attr">icon</span>: L.divIcon({
        <span class="hljs-attr">className</span>: <span class="hljs-string">'icon'</span>,
        html
      }),
      <span class="hljs-attr">riseOnHover</span>: <span class="hljs-literal">true</span>
    });
  }
});
</code></pre>
<p>So what are we doing here?</p>
<ul>
<li>We create a new instance of <code>L.GeoJSON</code> which will transform our GeoJSON document into something Leaflet will understand</li>
<li>Inside that instance, we define a custom <code>pointToLayer</code> function. This allows us to customize the map layer Leaflet creates for our map</li>
<li>In our function, we assign and create our datapoints that we want. Most of it is destructuring, but we format the cases count to show <code>1k+</code> instead of <code>1000</code> and a formatted date instead of the timestamp</li>
<li>We create an HTML string block which is used to define our map marker that will be added to the map. This also includes the HTML for the tooltip that will pop up when hovering over a marker</li>
<li>We return <code>L.marker</code> with our custom configuration that includes a class of <code>icon</code> for the container and our custom HTML.</li>
<li>Additionally, we add the <code>riseOnHover</code> property so when hoving over a marker, it surfaces itself above over the other markers on the map</li>
</ul>
<p>We also want to add a bit of CSS here so that we can make sure our markers show up in the map and are usable. Let’s add this snippet to our <code>assets/stylesheets/components/_map.scss</code> file:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.icon-marker</span> {

  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">3.6em</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">3.6em</span>;
  <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">7em</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$red-800</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">2px</span> <span class="hljs-number">5px</span> rgba(black, .<span class="hljs-number">9</span>);

  &amp;<span class="hljs-selector-pseudo">:hover</span> {

    <span class="hljs-selector-class">.icon-marker-tooltip</span> {
      <span class="hljs-attribute">display</span>: block;
    }

  }

}

<span class="hljs-selector-class">.icon-marker-tooltip</span> {

  <span class="hljs-attribute">display</span>: none;
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">bottom</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">16em</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.4em</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
  <span class="hljs-attribute">border-radius</span>: .<span class="hljs-number">4em</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">3px</span> <span class="hljs-number">5px</span> rgba(black, .<span class="hljs-number">9</span>);

  &amp;<span class="hljs-selector-pseudo">:before</span> {
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">bottom</span>: -.<span class="hljs-number">6em</span>;
    <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
    <span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">1.4em</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">1.4em</span>;
    <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
    <span class="hljs-attribute">transform</span>: rotate(<span class="hljs-number">45deg</span>);
    <span class="hljs-attribute">margin-left</span>: -.<span class="hljs-number">7em</span>;
  }

  <span class="hljs-selector-tag">h2</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.5em</span>;
    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.2</span>;
    <span class="hljs-attribute">margin-bottom</span>: .<span class="hljs-number">1em</span>;
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">0</span>;
  }

  <span class="hljs-selector-tag">h3</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2em</span>;
    <span class="hljs-attribute">margin</span>: .<span class="hljs-number">1em</span> <span class="hljs-number">0</span>;
    <span class="hljs-attribute">font-weight</span>: normal;
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$blue-grey-100</span>;
  }

  <span class="hljs-selector-tag">ul</span>,
  <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">font-weight</span>: normal;
  }

  <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin</span>: .<span class="hljs-number">6em</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  }

}
</code></pre>
<p>What we’re doing:</p>
<ul>
<li>We create our round markers using the <code>.icon-marker</code> class and set up our <code>.icon-marker-tooltip</code> class to show up when hovered over</li>
<li>Our <code>.icon-marker-tooltip</code> class is hidden by default, as it’s our tooltip, but we position it absolutely to appear over top of our marker and formatted the way we want it</li>
</ul>
<p>And finally, once we have our <code>geoJsonLayers</code> created with our styling added, we can add it to the map!</p>
<pre><code>geoJsonLayers.addTo(map)
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/03/map-with-coronavirus-location-data.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Map with Coronavirus location data</em></p>
<p>Now you might be wondering why it doesn't appear to be centering properly. Go ahead and change the <code>LOCATION</code> variable at the top of the <code>index.js</code> file to:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> LOCATION = {
  <span class="hljs-attr">lat</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">lng</span>: <span class="hljs-number">0</span>
};
</code></pre>
<p>Once that’s set, when the page reloads, the map should be centered in the middle of the world!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/map-with-coronavirus-location-data-centered-tooltip.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Map with Coronavirus location data centered with a tooltip</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/49c78e4ef3e98c974fab7bca10b6f8f7578b42c2">Follow along with the commit!</a></p>
<h2 id="heading-yay-we-did-it">Yay, we did it! ?</h2>
<p>If you followed along, you now have created your own Coronavirus map dashboard that gives some quick stats about the cases around the world.</p>
<p>Take what you learned and run with it. You can apply this to any other type of data that you can imagine.</p>
<h2 id="heading-what-else-can-we-do">What else can we do?</h2>
<h3 id="heading-add-more-styles-and-a-custom-basemap">Add more styles and a custom basemap</h3>
<p>In my original demo, I set up a custom basemap using <a target="_blank" href="https://mapbox.com/">Mapbox</a> that allows me to have a dark background making the markers easier to see.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/mapbox-studio-basemap.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new basemap in Mapbox Studio</em></p>
<p>Mapbox is great and has a nice free tier if you’re interested in getting started.</p>
<p>Once you have a Mapbox account, you can even <a target="_blank" href="https://api.mapbox.com/styles/v1/colbyfayock/ck8c2foj72lqk1jnug0g2haw0.html?fresh=true&amp;title=copy&amp;access_token=pk.eyJ1IjoiY29sYnlmYXlvY2siLCJhIjoiY2swODZzbXYxMGZzdzNjcXczczF6MnlvcCJ9.HCfgUYZUTP7uixjYF7tBSw">copy the style</a> I used and make it your own.</p>
<p><a target="_blank" href="https://api.mapbox.com/styles/v1/colbyfayock/ck8c2foj72lqk1jnug0g2haw0.html?fresh=true&amp;title=copy&amp;access_token=pk.eyJ1IjoiY29sYnlmYXlvY2siLCJhIjoiY2swODZzbXYxMGZzdzNjcXczczF6MnlvcCJ9.HCfgUYZUTP7uixjYF7tBSw">Basic Dark Mapbox Theme</a></p>
<p>To learn how to integrate it, you can try to check out the source code of <a target="_blank" href="https://github.com/colbyfayock/coronavirus-map-dashboard">my original demo</a>:</p>
<p><a target="_blank" href="https://github.com/colbyfayock/coronavirus-map-dashboard">https://github.com/colbyfayock/coronavirus-map-dashboard</a></p>
<h3 id="heading-add-overview-dashboard-stats">Add overview dashboard stats</h3>
<p>Dashboards with maps like the <a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Johns Hopkins University app</a> allows us to see more than a look on the map, but a glimpse at quick stats about the cases around the world.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/johns-hopkins-coronavirus-map-march-29.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Johns Hopkins University Coronavirus Map Dashboard - March 29, 2020</em></p>
<p>The <a target="_blank" href="https://github.com/NovelCOVID/API">NovelCOVID API</a> has more endpoints like <code>/all</code> that provide a few global stats.</p>
<h2 id="heading-be-safe-and-stay-informed">Be safe and stay informed</h2>
<p>I want to reiterate that you should make sure you're staying up to date using official sources for information, such as the Johns Hopkins University dashboard. Though the data should be reliable, it should also be considered a proof of concept for building a map and referencing, but shouldn't be considered for any kind of statistical analysis.</p>
<p>Please take care of yourself during these times. We're all in this together! ❤️</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter/">How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<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>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet ]]>
                </title>
                <description>
                    <![CDATA[ Get ready for the summer by building your own road trip mapping app with this step-by-step guide! What are we going to build? What do we need before we get started? Step 1: Cleaning up some unneeded code Step 2: Create our road trip locations Step 3... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet/</link>
                <guid isPermaLink="false">66b8e3556a98b2a27ee1f34a</guid>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 24 Mar 2020 13:01:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/road-trip-mapping-app-2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Get ready for the summer by building your own road trip mapping app with this step-by-step guide!</p>
<ul>
<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-what-do-we-need-before-we-get-started">What do we need before we get started?</a></li>
<li><a class="post-section-overview" href="#id=&quot;step-1-cleaning-up-some-unneeded-code&quot;">Step 1: Cleaning up some unneeded code</a></li>
<li><a class="post-section-overview" href="#heading-step-2-create-our-road-trip-locations">Step 2: Create our road trip locations</a></li>
<li><a class="post-section-overview" href="#heading-step-3-prepare-our-app-with-some-functions">Step 3: Prepare our app with some functions</a></li>
<li><a class="post-section-overview" href="#heading-step-4-building-our-trip-path">Step 4: Building our trip path</a></li>
<li><a class="post-section-overview" href="#heading-step-5-styling-our-map-components">Step 5: Styling our map components</a></li>
<li><a class="post-section-overview" href="#heading-want-to-learn-more-about-maps">Want to learn more about maps?</a></li>
</ul>
<p><em>Author’s Note: Even though we’re going through some challenging times, we can still be optimistic that we’ll get through this together and be able to enjoy our summer. Stay safe and wash your hands. ❤️</em></p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/FkO8uggDEXY" 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-we-going-to-build">What are we going to build?</h2>
<p>We’ll be walking through building a new mapping app that shows a route representing the trip. Each location will have a little card where we can add a picture and some things we did.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/summer-road-trip-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://summer-road-trip.netlify.com/">Colbana's Summer Road Trip</a></em></p>
<p>To get started, we’re going to use this <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a> I created to make the initial setup a little smoother. With our app bootstrapped, we’ll create our list of locations and use Leaflet’s API to draw our route on the map.</p>
<h2 id="heading-woah-a-mapping-app">Woah, a mapping app?</h2>
<p>Yup. If you haven’t played with maps before, don’t be discouraged! It's not as bad as you probably think. If you’d rather start with mapping basics, you can <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">read more about how mapping works</a> first.</p>
<h2 id="heading-what-do-we-need-before-we-get-started">What do we need before we get started?</h2>
<p>If you followed along with my last tutorial for <a target="_blank" href="https://www.freecodecamp.org/news/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">building a Santa Tracker</a>, you can follow the same steps to get started. If not, we’ll want to make sure we have the following set up:</p>
<ul>
<li><a target="_blank" href="https://nodejs.org/en/">node</a> or <a target="_blank" href="https://yarnpkg.com/en/">yarn</a> - I'll be using yarn, but you can substitute with npm where appropriate</li>
<li><a target="_blank" href="https://www.gatsbyjs.org/docs/gatsby-cli/">Gatsby’s CLI</a> - <code>yarn global add gatsby-cli</code></li>
</ul>
<p>If you’re not sure about one of the above items, you can try checking out the beginning of <a target="_blank" href="https://www.freecodecamp.org/news/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">my previous tutorial</a>.</p>
<p>We’ll also want to set up a foundation for our map. We can do this by utilizing the Leaflet Gatsby Starter I put together that provides us a basic setup with <a target="_blank" href="https://leafletjs.com/">Leaflet</a> and <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a>.</p>
<pre><code class="lang-shell">gatsby new my-road-trip https://github.com/colbyfayock/gatsby-starter-leaflet
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/terminal-creating-new-gatsby-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new Leaflet Gatsby app in the terminal</em></p>
<p>After that’s finished running, you can navigate to the newly created project directory and start your local development server:</p>
<pre><code class="lang-shell">cd my-road-trip
yarn develop
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/terminal-starting-gatsby-development-server.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Starting your Gatsby app in the terminal</em></p>
<p>If all goes as planned, your server should start and you should now be able to see your basic mapping app in your browser!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/gatsby-starter-leaflet-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Leaflet Gatsby app in the browser</em></p>
<h2 id="heading-step-1-cleaning-up-some-unneeded-code">Step 1: Cleaning up some unneeded code</h2>
<p>The Gatsby Starter we're using to spin up this app comes with some demo code that we don’t need here. We’ll want to make all of the changes below in the file <code>src/pages/index.js</code>, which is the homepage of our app.</p>
<p>First, let’s remove everything from the <code>mapEffect</code> function. This function is used to run code that fires when the map renders.</p>
<pre><code class="lang-js"><span class="hljs-comment">// In src/pages/index.js</span>

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement } = {}</span>) </span>{
  <span class="hljs-comment">// Get rid of everything in here</span>
}
</code></pre>
<p>Next, we don’t want a marker this time, so let’s remove the <code>&lt;Marker</code> component from our <code>&lt;Map</code> component:</p>
<pre><code class="lang-jsx">&lt;<span class="hljs-built_in">Map</span> {…mapSettings} /&gt;
</code></pre>
<p>Now that we have those pieces cleared out, we can remove all of the following imports and variables from the top of our file:</p>
<ul>
<li>useRef</li>
<li>Marker</li>
<li>promiseToFlyTo</li>
<li>getCurrentLocation</li>
<li>gatsby_astronaut</li>
<li>timeToZoom</li>
<li>timeToOpenPopupAfterZoom</li>
<li>timeToUpdatePopupAfterZoom</li>
<li>ZOOM</li>
<li>popupContentHello</li>
<li>popupContentGatsby</li>
<li>markerRef</li>
</ul>
<p>After, our map should still work, but not do anything.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/new-empty-mapping-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New mapping app with nothing going on</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-road-trip/commit/c92e8f970c8a2f2436f65ea0890680a88b747c49">Follow along with the commit</a></p>
<h2 id="heading-step-2-create-our-road-trip-locations">Step 2: Create our road trip locations</h2>
<p>This step will involve preparing our location data that will populate our road trip app. Our locations will include properties like a name, date, things we did, and a picture if we want.</p>
<p>First, create a new file in the <code>src/data</code> directory called <code>locations.js</code>.  Inside of that file, we want to create and export a new array.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> locations = [
  {
    <span class="hljs-attr">placename</span>: ‘Herndon, VA’,
    <span class="hljs-attr">date</span>: ‘August <span class="hljs-number">1</span>, <span class="hljs-number">2015</span>’,
    <span class="hljs-attr">location</span>: {
      <span class="hljs-attr">lat</span>: <span class="hljs-number">38.958988</span>,
      <span class="hljs-attr">lng</span>: <span class="hljs-number">-77.417320</span>
    },
    <span class="hljs-attr">todo</span>: [
      ‘Where we start! ?’
    ]
  },
  {
    <span class="hljs-attr">placename</span>: ‘Middlesboro, KY<span class="hljs-string">',
    date: ‘August 1, 2015’,
    location: {
      lat: 36.627517,
      lng: -83.621635
    },
    todo: [
      ‘Cumberland Gap ?’
    ]
  }
];</span>
</code></pre>
<p>You can use the above to get started, but you’ll eventually want to change the details to something of your choosing.</p>
<p>If you want to add an image to your location, you can do so by including an <code>image</code> property to the object. You can use either a URL string or you can import a local file if you have one available, like I’m doing in this example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> imgHerndonStart <span class="hljs-keyword">from</span> <span class="hljs-string">'assets/images/herndon-start.jpg’;

export const locations = [
  {
    placename: ‘Herndon, VA’,
    date: ‘August 1, 2015’,
    image: imgHerndonStart,
    location: {
      lat: 38.958988,
      lng: -77.417320
    },
    todo: [
      ‘Where we start! ?’
    ]
  }
]</span>
</code></pre>
<p>Once we have that file created, we can now import our locations into our <code>src/pages/index.js</code> file so we can use it in our next step:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { locations } <span class="hljs-keyword">from</span> <span class="hljs-string">'data/locations’;</span>
</code></pre>
<p>If you add a <code>console.log(locations)</code> inside of your page, you should now see all of your location data in an array!</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-road-trip/commit/55f4eb32d402364a20ad0342ebfde995081c521e">Follow along with the commit</a></p>
<h2 id="heading-step-3-prepare-our-app-with-some-functions">Step 3: Prepare our app with some functions</h2>
<p>To try to keep things simple and focused, I grouped together 3 important components of creating our map into functions. Though it’s available to copy and paste, we’ll walk through what’s happening in each function.</p>
<p>You can place each of these functions at the bottom of the <code>src/pages/index.js</code> file so they’re ready to use in our next step.</p>
<h3 id="heading-createtrippointsgeojson">createTripPointsGeoJson</h3>
<p>Our first function is going to take the array of our locations and return a <a target="_blank" href="https://geojson.org/">GeoJSON document</a>, with our locations mapped into an individual Feature. We’ll use this function to create the individual points on our map.</p>
<p>What is a GeoJSON document? It's essentially a JavaScript object or JSON document with a specific structure that creates consistency with geographical data.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createTripPointsGeoJson</span>(<span class="hljs-params">{ locations } = {}</span>) </span>{
  <span class="hljs-keyword">return</span> {
    “type”: “FeatureCollection”,
    “features”: locations.map(<span class="hljs-function">(<span class="hljs-params">{ placename, location = {}, image, date, todo = [] } = {}</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> { lat, lng } = location;
      <span class="hljs-keyword">return</span> {
        “type”: “Feature”,
        “properties”: {
          placename,
          todo,
          date,
          image
        },
        “geometry”: {
          “type”: “Point”,
          “coordinates”: [ lng, lat ]
        }
      }
    })
  }
}
</code></pre>
<p>So what’s happening in the above?</p>
<ul>
<li>We take an argument of locations, which will be our array of destinations</li>
<li>We return an object with some dynamic properties associated with it</li>
<li>Within the object, we map our locations to individual <code>Feature</code> objects</li>
<li>Each object includes a <code>Point</code> shape using our coordinates</li>
<li>It additionally includes our properties that store our metadata</li>
</ul>
<p>When this function is invoked, we will have a newly created JavaScript object that includes an array of Points representing the locations we are stopping at on our road trip.</p>
<h3 id="heading-createtriplinesgeojson">createTripLinesGeoJson</h3>
<p>We’re going to create another function that’s similar to the previous one. This time however, instead of points, we want to create lines that represent going from one point to the next.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createTripLinesGeoJson</span>(<span class="hljs-params">{ locations } = {}</span>) </span>{
  <span class="hljs-keyword">return</span> {
    “type”: “FeatureCollection”,
    “features”: locations.map(<span class="hljs-function">(<span class="hljs-params">stop = {}, index</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> prevStop = locations[index - <span class="hljs-number">1</span>];

      <span class="hljs-keyword">if</span> ( !prevStop ) <span class="hljs-keyword">return</span> [];

      <span class="hljs-keyword">const</span> { placename, location = {}, date, todo = [] } = stop;
      <span class="hljs-keyword">const</span> { lat, lng } = location;
      <span class="hljs-keyword">const</span> properties = {
        placename,
        todo,
        date
      };

      <span class="hljs-keyword">const</span> { <span class="hljs-attr">location</span>: prevLocation = {} } = prevStop;
      <span class="hljs-keyword">const</span> { <span class="hljs-attr">lat</span>: prevLat, <span class="hljs-attr">lng</span>: prevLng } = prevLocation;

      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">type</span>: ‘Feature’,
        properties,
        <span class="hljs-attr">geometry</span>: {
          <span class="hljs-attr">type</span>: ‘LineString’,
          <span class="hljs-attr">coordinates</span>: [
            [ prevLng, prevLat ],
            [ lng, lat ]
          ]
        }
      }
    })
  }
}
</code></pre>
<p>So you’ll immediately notice that this is very similar to our last function. We’re returning an object and setting our metadata properties on a list of Features.</p>
<p>The big difference, however, is that we're creating a Line. To do this, we're looking up and referring to <code>prevStop</code> which will be the previous stop. We’ll use both the previous stop and our current stop in order to have 2 points which we can use to draw the line. </p>
<p>If we don’t have a previous stop, we return an empty array, which basically means we’re at the beginning of our journey with no line before it.</p>
<p>With the previous stop and current stop, we create a <code>LineString</code> type of Feature with our 2 points.</p>
<h3 id="heading-tripstoppointtolayer">tripStopPointToLayer</h3>
<p>Our last function is going to allow us to create custom content for each of the points that we will be adding to our map. We’ll actually be utilizing this function within a Leaflet property, so we’ll be conforming our arguments to that specification.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">tripStopPointToLayer</span>(<span class="hljs-params"> feature = {}, latlng </span>) </span>{
  <span class="hljs-keyword">const</span> { properties = {} } = feature;
  <span class="hljs-keyword">const</span> { placename, todo = [], image, date } = properties;

  <span class="hljs-keyword">const</span> list = todo.map(<span class="hljs-function"><span class="hljs-params">what</span> =&gt;</span> <span class="hljs-string">`&lt;li&gt;<span class="hljs-subst">${ what }</span>&lt;/li&gt;`</span>);
  <span class="hljs-keyword">let</span> listString = ‘’;
  <span class="hljs-keyword">let</span> imageString = ‘’;

  <span class="hljs-keyword">if</span> ( <span class="hljs-built_in">Array</span>.isArray(list) &amp;&amp; list.length &gt; <span class="hljs-number">0</span> ) {
    listString = list.join(‘’);
    listString = <span class="hljs-string">`
      &lt;p&gt;Things we will or have done…&lt;/p&gt;
      &lt;ul&gt;<span class="hljs-subst">${listString}</span>&lt;/ul&gt;
    `</span>
  }

  <span class="hljs-keyword">if</span> ( image ) {
    imageString = <span class="hljs-string">`
      &lt;span class=“trip-stop-image” style=“background-image: url(<span class="hljs-subst">${image}</span>)”&gt;<span class="hljs-subst">${placename}</span>&lt;/span&gt;
    `</span>;
  }

  <span class="hljs-keyword">const</span> text = <span class="hljs-string">`
    &lt;div class=“trip-stop”&gt;
      <span class="hljs-subst">${ imageString }</span>
      &lt;div class=“trip-stop-content”&gt;
        &lt;h2&gt;<span class="hljs-subst">${placename}</span>&lt;/h2&gt;
        &lt;p class=“trip-stop-date”&gt;<span class="hljs-subst">${date}</span>&lt;/p&gt;
        <span class="hljs-subst">${ listString }</span>
      &lt;/div&gt;
    &lt;/div&gt;
  `</span>;

  <span class="hljs-keyword">const</span> popup = L.popup({
    <span class="hljs-attr">maxWidth</span>: <span class="hljs-number">400</span>
  }).setContent(text);

  <span class="hljs-keyword">const</span> layer = L.marker( latlng, {
    <span class="hljs-attr">icon</span>: L.divIcon({
      <span class="hljs-attr">className</span>: ‘icon’,
      <span class="hljs-attr">html</span>: <span class="hljs-string">`&lt;span class=“icon-trip-stop”&gt;&lt;/span&gt;`</span>,
      <span class="hljs-attr">iconSize</span>: <span class="hljs-number">20</span>
    }),
    <span class="hljs-attr">riseOnHover</span>: <span class="hljs-literal">true</span>
  }).bindPopup(popup);

  <span class="hljs-keyword">return</span> layer;
}
</code></pre>
<p>One thing you’ll notice as we work through this function is that we create strings of HTML text. Given that the Leaflet API we’re utilizing for this doesn’t interface directly with React, we have to build out HTML manually to pass it in to our functions.</p>
<p>Starting from the top:</p>
<ul>
<li>We take in 2 arguments, <code>feature</code> and <code>latlng</code>. Leaflet passes these 2 values in for us to use in our function.</li>
<li>We destructure our feature, allowing us to assign our metadata into variables</li>
<li>2 string variables are initialized that we’ll use for our HTML</li>
<li>If we include a <code>todo</code> property as an array, we add a new list with each item inside.</li>
<li>If we include an image, we create an image tag.</li>
<li>With our newly created HTML strings, we construct the entirety of what will be our popup card for each strop</li>
<li>With our popup HTML, we create a Leaflet <code>popup</code> instance</li>
<li>With the latlng argument and our popup, we create a new Leaflet <code>marker</code>  instance. This will represent the point on the map.</li>
<li>Inside of the Marker creation, we create a basic HTML tag that well use to style the marker</li>
<li>We then bind our popup to this new Marker instance. This will allow the popup to be associated with that individual Marker</li>
<li>Finally, we return our newly created layer</li>
</ul>
<p>Remember to make sure you put all of the functions above at the bottom of your <code>src/pages/index.js</code> page.</p>
<p>Once all of those functions are added, our map should still be the same thing, basically nothing happening.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-road-trip/commit/b27b644b32a11e4372963b9d16e0f7ec0ee74b65">Follow along with the commit</a></p>
<h2 id="heading-step-4-building-our-trip-path">Step 4: Building our trip path</h2>
<p>This is where things get interesting. We’ll now utilize the functions we created to build our road trip path. All of our work here will be within the <code>mapEffect</code> function inside of the <code>src/pages/index.js</code> file.</p>
<p>For context, our <code>mapEffect</code> function includes an argument called <code>leafletElement</code>. This value refers to the Map instance that Leaflet recognizes. This Map instance includes our map state as well as many utility functions to work with our map.</p>
<p>First, at the top of the function, we want to make sure we have a map. If not, we can return to bail out of the function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> ( !leafletElement ) <span class="hljs-keyword">return</span>;
</code></pre>
<p>Next, we want to use the <code>eachLayer</code> utility function and remove each <code>layer</code> from our map element. We do this to make sure we always have the correct map layer state.</p>
<pre><code class="lang-js">leafletElement.eachLayer(<span class="hljs-function">(<span class="hljs-params">layer</span>) =&gt;</span> leafletElement.removeLayer(layer));
</code></pre>
<p>With our cleaned up map, we can utilize 2 of the functions we created to create new GeoJSON objects.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> tripPoints = createTripPointsGeoJson({ locations });
<span class="hljs-keyword">const</span> tripLines = createTripLinesGeoJson({ locations });
</code></pre>
<p>With our GeoJSON objects, we need to convert those to Leaflet GeoJSON instances, which we’ll use to add to the map.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> tripPointsGeoJsonLayers = <span class="hljs-keyword">new</span> L.geoJson(tripPoints, {
  <span class="hljs-attr">pointToLayer</span>: tripStopPointToLayer
});

<span class="hljs-keyword">const</span> tripLinesGeoJsonLayers = <span class="hljs-keyword">new</span> L.geoJson(tripLines);
</code></pre>
<p>If you notice in the above, we're using our <code>tripStopPointToLayer</code> function. As I alluded to before, the <code>geoJson</code> instance we’re creating includes a property that allows us to pass in a function, giving us the ability to manipulate the layer creation. This is how we create our point and popup content.</p>
<p>We can proceed to adding both of those new layers to our map using the <code>addTo</code> .</p>
<pre><code class="lang-js">tripPointsGeoJsonLayers.addTo(leafletElement);
tripLinesGeoJsonLayers.addTo(leafletElement);
</code></pre>
<p>Next, to make sure we zoom and center on the right location, we want to grab the bounds of the map using the <code>getBounds</code> function on our GeoJSON layer instance.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bounds = tripPointsGeoJsonLayers.getBounds();
</code></pre>
<p>Finally, we fit our map's view to those bounds using the <code>fitBounds</code> function on our Map instance.</p>
<pre><code class="lang-js">leafletElement.fitBounds(bounds);
</code></pre>
<p>Once you save  and reload the page, you should now see a blue path representing the jump from each of our locations on the map!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/mapping-app-with-road-trip-path.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapping app with road trip path</em></p>
<p>One issue though. If you notice, we only see the path. This is because we need to add some CSS which we’ll get to in the next step.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-road-trip/commit/6b3f079bebdd60bf012c0886fc33547c98ea50f5">Follow along with the commit</a></p>
<h2 id="heading-step-5-styling-our-map-components">Step 5: Styling our map components</h2>
<p>Our last step will be adding some styles that will allow our markers to show and our popups to look just right.</p>
<p>In this step, we’ll be working inside of the <code>_home.scss</code> file, which you can find in <code>src/assets/stylesheets/pages</code>.</p>
<p>We can get started by copy and pasting this block of styles into the bottom of that file. With that done, we can walk through what’s happening.</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.trip-stop</span> {

  <span class="hljs-attribute">width</span>: <span class="hljs-number">400px</span>;
  <span class="hljs-attribute">overflow</span>: hidden;

  <span class="hljs-selector-tag">h2</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.4em</span>;
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin-bottom</span>: .<span class="hljs-number">2em</span>;
  }

  <span class="hljs-selector-tag">p</span>,
  <span class="hljs-selector-tag">ul</span>,
  <span class="hljs-selector-tag">h3</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2em</span>;
    <span class="hljs-attribute">font-weight</span>: normal;
  }

  <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">margin</span>: .<span class="hljs-number">2em</span> <span class="hljs-number">0</span>;
  }

  <span class="hljs-selector-class">.trip-stop-date</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$grey-600</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1em</span>;
  }

  <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">1.4em</span>;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  }

}

<span class="hljs-selector-class">.trip-stop-image</span> {
  <span class="hljs-attribute">display</span>: block;
  <span class="hljs-attribute">float</span>: left;
  <span class="hljs-attribute">overflow</span>: hidden;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">150px</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">150px</span>;
  <span class="hljs-attribute">text-indent</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">color</span>: transparent;
  <span class="hljs-attribute">background-position</span>: center;
  <span class="hljs-attribute">background-size</span>: cover;
}

<span class="hljs-selector-class">.trip-stop-content</span> {
  <span class="hljs-attribute">float</span>: left;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">250px</span>;
  <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">1em</span>;
}

<span class="hljs-selector-class">.icon-trip-stop</span> {

  <span class="hljs-attribute">display</span>: block;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">1.5em</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">1.5em</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$orange-500</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">2px</span> <span class="hljs-number">5px</span> rgba(<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,.<span class="hljs-number">5</span>);

  &amp;<span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$deep-orange-400</span>;
  }

}
</code></pre>
<p>There’s three components to our styles above:</p>
<ul>
<li><code>.trip-stop-images</code>: Inside of the marker popup, we optionally can include an image. These styles set the size, make the text transparent, (it’s there for accessibility), and float it to the left so that our popup content can align correctly side by side.</li>
<li><code>.trip-stop-content</code>: This refers to the other half of our popup content. All we need to do here is make sure our size is appropriate and that it floats next to our image.</li>
<li><code>.icon-trip-stop</code>: The HTML tag that we’re using as our icon designation gets styled here. We size it up, set a color using a predetermined Scss variable, and we’re good to go.</li>
</ul>
<p>Once those styles are saved, you should now see the points on the map representing each location. Additionally, you should be able to click each of these points to open up a popup containing information about the stop.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/road-trip-mapping-app-with-popup.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Road trip mapping app with popups</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-road-trip/commit/d2bac5c1b04a32837366de6f15f14d5342134d38">Follow along with the commit</a></p>
<h2 id="heading-optional-last-step-style-tweaks">Optional Last Step: Style Tweaks</h2>
<p>The last thing that's completely optional is to make a few style tweaks to give your site a little personality. I’m not going to go over this in details, but if you’d like to follow along and dress things up a little bit, you can follow along with <a target="_blank" href="https://github.com/colbyfayock/my-road-trip/commit/c2c667da6e34595bc6d8dd0ee66e55d4155feed2">this commit</a> which shows each code change I made.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/road-trip-mapping-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Final version of the road trip mapping app</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-road-trip/commit/c2c667da6e34595bc6d8dd0ee66e55d4155feed2">Follow along with the commit</a></p>
<h2 id="heading-yay-we-did-it">Yay, we did it!</h2>
<p>If you followed along with me, or skipped right to the starter, you should now have a mapping app that you can use for your next road trip.</p>
<p>The good news is this project can apply to anything! Want to map out your favorite restaurants in Washington, DC? Add your locations and remove the lines. Want to create line drawings over the map? That's certainly an option.</p>
<p>Whatever it is, if you enjoyed getting this map spun up, get creative and apply it to your next project!</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App in React with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter/">How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<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>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Anyone Can Map! Inspiration and an introduction to the world of mapping ]]>
                </title>
                <description>
                    <![CDATA[ Chef Gusteau was a visionary who created food experiences for the world to enjoy. How can we take his lessons and apply them to the world of mapping? Taking inspiration from a culinary great If you’ve seen the Pixar movie Ratatouille, you should know... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping/</link>
                <guid isPermaLink="false">66b8e31e47c23b7ae1ad0bd3</guid>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Heat map ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Inspiration ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 05 Mar 2020 14:51:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/anyone-can-map.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Chef Gusteau was a visionary who created food experiences for the world to enjoy. How can we take his lessons and apply them to the world of mapping?</p>
<h2 id="heading-taking-inspiration-from-a-culinary-great">Taking inspiration from a culinary great</h2>
<p>If you’ve seen the <a target="_blank" href="https://www.pixar.com/">Pixar</a> movie <a target="_blank" href="https://movies.disney.com/ratatouille">Ratatouille</a>, you should know who <a target="_blank" href="https://ratatouille.fandom.com/wiki/Auguste_Gusteau">Chef Gusteau</a> is. He helped our “little chef” <a target="_blank" href="https://pixar.fandom.com/wiki/Remy">Remy</a> the rat navigate the culinary world and become the top chef of Paris.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/ratatouille-remy-chef-gusteau-paris.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Remy from Ratatouille overlooking Gusteau's in Paris</em></p>
<p>Throughout the movie, we get a lot of great quotes on their journey. But the one we're interested in here is Gusteau’s motto, and the title of his book, “Anyone can cook!” So how can we apply this and the lessons to our own mapping journey?</p>
<p>I’ll admit, part of the fun here was translating some of the lessons learned from one of my favorite movies, but there’s a lot to take in here. I'm going to walk through some examples and types of maps that should get you motivated to get started with your own mapping application. So let’s dive in!</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/pQ_5PGv0YTA" 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-get-inspired-by-learning-about-maps-and-the-impact-they-have-on-the-world">Get inspired by learning about maps and the impact they have on the world</h2>
<blockquote>
<p>Food always comes to those who love to cook. - Chef Gusteau</p>
</blockquote>
<p><a target="_blank" href="https://www.youtube.com/watch?v=a-1rcaQ-aSk&amp;list=PLeGxIOPLk9EKBu_B0WpBLYkkHQIGki2EZ&amp;index=3">Through my work</a>, I’ve found it easy to fall in love with working on maps. Every day, scientists use maps to visualize data that can assist them in making more effective decisions. This directly translates to benefitting people all around the world and saving lives.</p>
<p>With this inspiration, you'll be taken on a journey to learn more about the different types of maps in this world and how they’re being used. You even might stumble upon some interesting data that explores your own neighborhood!</p>
<h3 id="heading-active-fires-around-the-world">Active fires around the world</h3>
<p>Take for instance <a target="_blank" href="https://firms.modaps.eosdis.nasa.gov/map/">NASA’s FIRMS service</a>, which provides a realtime look at active fire data around the world.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/nasa-firms-active-fires-world.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Active fires around the world via <a target="_blank" href="https://earthdata.nasa.gov/earth-observation-data/near-real-time/firms">NASA FIRMS</a></em></p>
<p>Fires are a real-world example of disasters that we can learn from. This tool is used to help manage resources for stopping and preventing those fires by allowing scientists and those that are curious to analyze burn areas and model the data itself.</p>
<h3 id="heading-global-cases-of-covid-19">Global cases of COVID-19</h3>
<p>And something very current, cases of <a target="_blank" href="https://www.who.int/health-topics/coronavirus">COVID-19 (Coronavrius)</a> around the world by  <a target="_blank" href="https://systems.jhu.edu/">Johns Hopkins Center for Systems Science and Engineering</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/john-hopkins-coronavirus-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Global cases of Coronavirus (COVID-19) from John Hopkins CSSE</a></em></p>
<p>This map tracks the spread of the virus in real time, allowing scientists to model it's coverage and produce study results to share with the global community.</p>
<p>Mapping tools like this provide an effective means of giving as much information as possible in a way that’s easy to understand to the people who can make a difference with the information.</p>
<h3 id="heading-increased-life-expectancy">Increased life expectancy</h3>
<p>On a more positive note, we can get a detailed look over time of <a target="_blank" href="https://ourworldindata.org/life-expectancy">how life expectancy is improving around the world</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/life-expectancy-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://ourworldindata.org/life-expectancy">Life expectancy in 2019 from Our World in Data</a></em></p>
<p>While it’s increased more in some areas than others, the global improvements are clear, and we get to see this rise in some countries from hundreds of years ago!</p>
<h2 id="heading-explore-the-beauty-of-maps-and-applying-data-to-them">Explore the beauty of maps and applying data to them</h2>
<blockquote>
<p>How can I describe it? Good food is like music you can taste, color you can smell. There is excellence all around you. You need only to be aware to stop and savor it. - Chef Gusteau</p>
</blockquote>
<p>There’s also a creative side and beauty to great maps. Thick datasets applied to a map (or any medium) can often become literal works of art.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/pentagram-the-room-of-change.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.pentagram.com/work/the-room-of-change?rel=discipline&amp;rel-id=16">The Room of Change from Pentagram</a></em></p>
<p>Whether showcased in an exhibit or <a target="_blank" href="https://www.etsy.com/search?q=map">one of the many options to purchase on Etsy</a>, presenting meaningful data in a beautiful way can be impactful not just from an informational perspective, but also a cultural one.</p>
<h3 id="heading-sometimes-the-interactions-can-be-fun">Sometimes the interactions can be fun</h3>
<p>Maps can also provide some interactivity that makes them fun to explore while you learn more about the dataset, like this globe that maps out global commodities from DailyFX.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/dailyfx-global-commodities.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.dailyfx.com/research/global-commodities/globe">Global Commodities interactive map from DailyFX</a></em></p>
<p>Though the data can frequently be thick and boring on its own, that doesn’t mean we can't find more interesting ways to present the data to interact with.</p>
<h3 id="heading-and-sometimes-maps-can-provide-a-listening-experience">And sometimes maps can provide a listening experience</h3>
<p>This map from at <a target="_blank" href="http://radiooooo.com/">radiooooo.com</a> allows you to travel around the world and through time.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/radiooooo-music-radio-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="http://radiooooo.com/">Music Radio from radiooooo.com</a></em></p>
<p>Their use of a map makes it easy to identify the part of the world the person wants to explore.</p>
<h3 id="heading-stop-and-appreciate-the-maps-around-you">Stop and appreciate the maps around you</h3>
<p>Whether you notice it or not when you’re browsing the web every day, you most likely run into visualizations of datasets that create powerful ways to present that data in a way that’s more easily understood.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/reddit-truck-driver-map-dataisbeautiful.jpg" alt="Image" width="600" height="400" loading="lazy">
_<a target="_blank" href="https://www.reddit.com/r/dataisbeautiful/comments/csl706/i_recorded_my_travels_as_a_professional_truck/">u/dancingchopstix's recordings of their truck driving travels</a>_</p>
<p>Luckily, we don’t have to work hard to find this inspiration, as we can visit aggregations of beautiful maps and general datasets like that of <a target="_blank" href="https://www.reddit.com/r/dataisbeautiful/">/r/dataisbeautiful</a>.</p>
<h2 id="heading-experiment-be-creative-explore-other-ways-to-visualize-data">Experiment, be creative, explore other ways to visualize data</h2>
<blockquote>
<p>You must be imaginative, strong-hearted. You must try things that may not work, and you must not let anyone define your limits because of where you come from. Your only limit is your soul. - Chef Gusteau</p>
</blockquote>
<p>Maps come in all shapes and sizes. While shaded geographic areas typically work well with election results, it might not work as well for showcasing your summer road trip.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/50-state-project-road-strip.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.the50statesproject.com/">50 State Project road trip map</a></em></p>
<h3 id="heading-exploring-common-map-types">Exploring common map types</h3>
<p>You’ve probably experienced more map types than you realize. Given it’s a powerful way to present data, maps are used frequently across the web.</p>
<p>A <a target="_blank" href="https://en.wikipedia.org/wiki/Choropleth_map"><strong>choropleth map</strong></a> is commonly seen for election results and regional datasets where a particular geographic location represents a point of reference.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/cnn-democratic-primary-2020.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.cnn.com/election/2020/primaries-and-caucuses">CNN Map of Democratic primary after Super Tuesday</a></em></p>
<p><strong><a target="_blank" href="https://en.wikipedia.org/wiki/Heat_map">Heat maps</a></strong> on the other hand allow you to reflect on the intensity of a data point over a given area. This is powerful when you want to represent both the area covered of a dataset but also range the data represents at the same time, such as population density.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/arcgis-population-heatmap-2015.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.arcgis.com/home/webmap/viewer.html?useExisting=1&amp;layers=90978c3a3a664c20b8da8fc21de6071b">ArcGIS GPW 2015 Population Density heat map from</a></em></p>
<h3 id="heading-learn-from-others-but-dont-be-afraid-to-create-a-new-path">Learn from others, but don’t be afraid to create a new path</h3>
<p>Explore and play around with different techniques to visualize data on a map. There’s frequently not one way to do it, meaning you can be creative and experiment with different ways of presenting your map.</p>
<p>But that also means you don’t need to be stuck working within the constraints of the common map types. Use the tools available or create new ones and break new ground. The most important thing is presenting the data in a way that will provide the most impact to those consuming it.</p>
<h2 id="heading-dont-give-up-learn-from-your-experiences">Don’t give up, learn from your experiences</h2>
<blockquote>
<p>What I say is true — anyone can cook... but only the fearless can be great. - Chef Gusteau</p>
</blockquote>
<p>While there may not always be a right way, there <a target="_blank" href="https://twitter.com/TerribleMaps">sometimes are wrong ways</a>.  But don’t let failure stop you!</p>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/TerribleMaps/status/1119336763762331649"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
<p>Take these failures as a learning experience in your journey of creating interesting and effective maps. By being bold with your experimentation, you’ll find yourself discovering techniques or creating new ways that can ultimately help people better understand map data.</p>
<h2 id="heading-you-dont-have-to-be-a-cartographer-to-build-great-maps">You don’t have to be a cartographer to build great maps</h2>
<blockquote>
<p>Not everyone can become a great artist; but a great artist can come from anywhere. - Anton Ego</p>
</blockquote>
<p>Towards the end of Remy’s journey, the food critic Anton Ego who was once critical of Gusteau's claim that “anyone can cook” came to a realization of what our chef truly meant.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/anton-ego-realization.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Ratatouille critic Anton Ego's revelation</em></p>
<p>While it’s not reasonable to assume that every single one of us will be a great mapper, everyone has the opportunity to try and explore the medium.</p>
<p>And it certainly helps that we have plenty of tooling to help us get there. Whether building your own with <a target="_blank" href="https://leafletjs.com/">Leaflet</a> or <a target="_blank" href="https://www.google.com/maps/about/mymaps/">identifying a few locations on a Google Map</a>, the resources and community around mapping are endless.</p>
<h2 id="heading-jump-in-with-some-resources-to-get-started">Jump in with some resources to get started</h2>
<p>For the developers out there who are inspired to get started, here are a few resources to start off with mapping:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/visualizing-air-pollution-folium-maps/">How to Visualize Air Pollution using Folium Maps - An In Depth Tutorial</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-integrate-maps-in-react-native-using-react-native-maps-5745490fe055/">How to integrate maps in React Native using react-native-maps</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App in React with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter/">How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=a-1rcaQ-aSk&amp;list=PLeGxIOPLk9EKBu_B0WpBLYkkHQIGki2EZ&amp;index=3">Building Maps with Impact on React and the JAMstack</a> (Video)</li>
<li><a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Gatsby Starter Leaflet</a></li>
<li><a target="_blank" href="https://leafletjs.com/">Leaflet</a></li>
<li><a target="_blank" href="https://openlayers.org/">OpenLayers</a></li>
<li><a target="_blank" href="https://www.google.com/maps/about/mymaps/">My Maps by Google</a></li>
</ul>
<h2 id="heading-whats-your-favorite-map-experience-or-tool">What’s your favorite map experience or tool?</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>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ JavaScript Standard Objects: Maps ]]>
                </title>
                <description>
                    <![CDATA[ The Map object is a relatively new standard built-in object that holds [key, value] pairs in the order that they're inserted.  The keys and values in the Map object can be any value (both objects and primitive values are valid). Syntax new Map([itera... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/javascript-standard-objects-maps/</link>
                <guid isPermaLink="false">66c3591ef83dfae169b2bff3</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ toothbrush ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 01 Feb 2020 00:00:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9d30740569d1a4ca3660.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The <code>Map</code> object is a relatively new standard built-in object that holds <code>[key, value]</code> pairs in the order that they're inserted. </p>
<p>The keys and values in the <code>Map</code> object can be any value (both objects and primitive values are valid).</p>
<h2 id="heading-syntax"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>([iterable])
</code></pre>
<h2 id="heading-parameters"><strong>Parameters</strong></h2>
<p><strong>iterable</strong> An Array or other iterable object whose elements are key-value pairs.</p>
<h2 id="heading-example"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
myMap.set(<span class="hljs-string">'foo'</span>, <span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>, <span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>, <span class="hljs-number">3</span>);

myMap.get(<span class="hljs-string">'foo'</span>);   <span class="hljs-comment">// returns 1</span>
myMap.get(<span class="hljs-string">'baz'</span>);   <span class="hljs-comment">// returns 3</span>
myMap.get(<span class="hljs-string">'hihi'</span>);  <span class="hljs-comment">// return undefined</span>

myMap.size;   <span class="hljs-comment">// 3</span>

<span class="hljs-built_in">console</span>.log(myMap); <span class="hljs-comment">// Map { 'foo' =&gt; 1, 'bar' =&gt; 2, 'baz' =&gt; 3 }</span>
</code></pre>
<p>It's easy to create a new <code>Map</code> from existing 2D arrays of key-value pairs:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myArr = [[<span class="hljs-string">'foo'</span>, <span class="hljs-number">1</span>], [<span class="hljs-string">'bar'</span>, <span class="hljs-number">2</span>], [<span class="hljs-string">'baz'</span>, <span class="hljs-number">3</span>]];
<span class="hljs-keyword">const</span> arrMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>(myArr);

<span class="hljs-built_in">console</span>.log(arrMap); <span class="hljs-comment">// Map { 'foo' =&gt; 1, 'bar' =&gt; 2, 'baz' =&gt; 3 }</span>
</code></pre>
<p>You can also convert an object into a <code>Map</code> with the help of the <code>Object.entries</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myObj = {
  <span class="hljs-attr">foo</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">bar</span>: <span class="hljs-number">2</span>,
  <span class="hljs-attr">baz</span>: <span class="hljs-number">3</span>
}
<span class="hljs-keyword">const</span> objMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>(<span class="hljs-built_in">Object</span>.entries(myObj));

<span class="hljs-built_in">console</span>.log(objMap); <span class="hljs-comment">// Map { 'foo' =&gt; 1, 'bar' =&gt; 2, 'baz' =&gt; 3 }</span>
</code></pre>
<h2 id="heading-mapprototypeget"><strong>Map.prototype.get</strong></h2>
<p>Returns the value of the specified key from a <code>Map</code> object.</p>
<h2 id="heading-syntax-1"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript">myMap.get(key);
</code></pre>
<h2 id="heading-parameters-1"><strong>Parameters</strong></h2>
<p><strong>key</strong> Required.</p>
<h2 id="heading-example-1"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
myMap.set(<span class="hljs-string">'foo'</span>,<span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>,<span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>,<span class="hljs-number">3</span>);

myMap.get(<span class="hljs-string">'foo'</span>);   <span class="hljs-comment">// returns 1</span>
myMap.get(<span class="hljs-string">'baz'</span>);   <span class="hljs-comment">// returns 3</span>
myMap.get(<span class="hljs-string">'hihi'</span>);  <span class="hljs-comment">// return undefined</span>
</code></pre>
<h2 id="heading-mapprototypeset"><strong>Map.prototype.set</strong></h2>
<p>Sets or updates an element with the specified key and value in a <code>Map</code> object. The <code>set()</code> method also returns the <code>Map</code> object.</p>
<h2 id="heading-syntax-2"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript">myMap.set(key, value);
</code></pre>
<h2 id="heading-parameters-2"><strong>Parameters</strong></h2>
<ul>
<li><strong>key</strong> Required</li>
<li><strong>value</strong> Required</li>
</ul>
<h2 id="heading-example-2"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

<span class="hljs-comment">// sets new elements</span>
myMap.set(<span class="hljs-string">'foo'</span>, <span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>, <span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>, <span class="hljs-number">3</span>);

<span class="hljs-comment">// Updates an existing element</span>
myMap.set(<span class="hljs-string">'foo'</span>, <span class="hljs-number">100</span>);

myMap.get(<span class="hljs-string">'foo'</span>);   <span class="hljs-comment">// returns 100</span>
</code></pre>
<p>Because <code>set()</code> returns the <code>Map</code> object it operated on, the method can be easily chained. For example, the code above can be simplified to:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

<span class="hljs-comment">// sets new elements</span>
myMap.set(<span class="hljs-string">'foo'</span>, <span class="hljs-number">1</span>)
  .set(<span class="hljs-string">'bar'</span>, <span class="hljs-number">2</span>)
  .set(<span class="hljs-string">'baz'</span>, <span class="hljs-number">3</span>)
  .set(<span class="hljs-string">'foo'</span>, <span class="hljs-number">100</span>); <span class="hljs-comment">// Updates an existing element</span>

myMap.get(<span class="hljs-string">'foo'</span>);   <span class="hljs-comment">// returns 100</span>
</code></pre>
<h2 id="heading-mapprototypesize"><strong>Map.prototype.size</strong></h2>
<p>Returns the number of elements in a <code>Map</code> object.</p>
<h2 id="heading-syntax-3"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript">myMap.size();
</code></pre>
<h2 id="heading-example-3"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
myMap.set(<span class="hljs-string">'foo'</span>,<span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>,<span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>,<span class="hljs-number">3</span>);


myMap.size(); <span class="hljs-comment">// 3</span>
</code></pre>
<h2 id="heading-mapprototypekeys"><strong>Map.prototype.keys</strong></h2>
<p>Returns a new <code>Iterator</code> object that contains the keys for each element in the <code>Map</code> object in insertion order.</p>
<h2 id="heading-syntax-4"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript">myMap.keys()
</code></pre>
<h2 id="heading-example-4"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
myMap.set(<span class="hljs-string">'foo'</span>,<span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>,<span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>,<span class="hljs-number">3</span>);


<span class="hljs-keyword">const</span> iterator = myMap.keys();

<span class="hljs-built_in">console</span>.log(iterator.next().value); <span class="hljs-comment">// 'foo'</span>
<span class="hljs-built_in">console</span>.log(iterator.next().value); <span class="hljs-comment">// 'bar'</span>
<span class="hljs-built_in">console</span>.log(iterator.next().value); <span class="hljs-comment">// 'baz'</span>
</code></pre>
<h2 id="heading-mapprototypevalues"><strong>Map.prototype.values</strong></h2>
<p>Returns an iterator object that contains the values for each element in the <code>Map</code> object in the order they were inserted.</p>
<h2 id="heading-syntax-5"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript">myMap.values()
</code></pre>
<h2 id="heading-example-5"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
myMap.set(<span class="hljs-string">'foo'</span>,<span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>,<span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>,<span class="hljs-number">3</span>);


<span class="hljs-keyword">const</span> iterator = myMap.values();
<span class="hljs-built_in">console</span>.log(iterator.next().value); <span class="hljs-comment">// 1</span>
<span class="hljs-built_in">console</span>.log(iterator.next().value); <span class="hljs-comment">// 2</span>
<span class="hljs-built_in">console</span>.log(iterator.next().value); <span class="hljs-comment">// 3</span>
</code></pre>
<h2 id="heading-mapprototypedelete"><strong>Map.prototype.delete</strong></h2>
<p>Removes the specified element from a <code>Map</code> object. Returns whether the key was found and successfully deleted.</p>
<h2 id="heading-syntax-6"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript">myMap.delete(key);
</code></pre>
<h2 id="heading-parameters-3"><strong>Parameters</strong></h2>
<p><strong>key</strong> Required.</p>
<h2 id="heading-example-6"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
myMap.set(<span class="hljs-string">'foo'</span>,<span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>,<span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>,<span class="hljs-number">3</span>);


myMap.size(); <span class="hljs-comment">// 3</span>
myMap.has(<span class="hljs-string">'foo'</span>); <span class="hljs-comment">// true;</span>

myMap.delete(<span class="hljs-string">'foo'</span>);  <span class="hljs-comment">// Returns true. Successfully removed.</span>

myMap.size(); <span class="hljs-comment">// 2</span>
myMap.has(<span class="hljs-string">'foo'</span>);    <span class="hljs-comment">// Returns false. The "foo" element is no longer present.</span>
</code></pre>
<h2 id="heading-mapprototypeentries"><strong>Map.prototype.entries</strong></h2>
<p>Returns a new <code>Iterator</code> object that contains the <code>[key, value]</code> pairs for each element in the <code>Map</code> object in insertion order.</p>
<h2 id="heading-syntax-7"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript">myMap.entries()
</code></pre>
<h2 id="heading-example-7"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
myMap.set(<span class="hljs-string">'foo'</span>,<span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>,<span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>,<span class="hljs-number">3</span>);


<span class="hljs-keyword">const</span> iterator = myMap.entries();

<span class="hljs-built_in">console</span>.log(iterator.next().value); <span class="hljs-comment">// ['foo', 1]</span>
<span class="hljs-built_in">console</span>.log(iterator.next().value); <span class="hljs-comment">// ['bar', 2]</span>
<span class="hljs-built_in">console</span>.log(iterator.next().value); <span class="hljs-comment">// ['baz', 3]</span>
</code></pre>
<h2 id="heading-mapprototypeclear"><strong>Map.prototype.clear</strong></h2>
<p>Removes all elements from a <code>Map</code> object and returns <code>undefined</code>.</p>
<h2 id="heading-syntax-8"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript">myMap.clear();
</code></pre>
<h2 id="heading-example-8"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
myMap.set(<span class="hljs-string">'foo'</span>,<span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>,<span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>,<span class="hljs-number">3</span>);


myMap.size(); <span class="hljs-comment">// 3</span>
myMap.has(<span class="hljs-string">'foo'</span>); <span class="hljs-comment">// true;</span>

myMap.clear(); 

myMap.size(); <span class="hljs-comment">// 0</span>
myMap.has(<span class="hljs-string">'foo'</span>); <span class="hljs-comment">// false</span>
</code></pre>
<h2 id="heading-mapprototypehas"><strong>Map.prototype.has</strong></h2>
<p>Given a <code>Map</code> with elements inside, the <code>has()</code> function allows you to determine whether or not an element exists inside the Map, based on a key that you pass.</p>
<p>The <code>has()</code> function returns a <em><code>Boolean</code> primitive</em> (either <code>true</code> or <code>false</code>), which indicates that the Map contains the element or not.</p>
<p>You pass a <code>key</code> parameter to the <code>has()</code> function, which will be used to look for an element with that key inside the Map.</p>
<p>Example:</p>
<pre><code class="lang-js"><span class="hljs-comment">// A simple Map</span>
<span class="hljs-keyword">const</span> campers = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

<span class="hljs-comment">// add some elements to the map</span>
<span class="hljs-comment">// each element's key is 'camp' and a number</span>
campers.set(<span class="hljs-string">'camp1'</span>, <span class="hljs-string">'Bernardo'</span>);
campers.set(<span class="hljs-string">'camp2'</span>, <span class="hljs-string">'Andrea'</span>);
campers.set(<span class="hljs-string">'camp3'</span>, <span class="hljs-string">'Miguel'</span>);

<span class="hljs-comment">// Now I want to know if there's an element</span>
<span class="hljs-comment">// with 'camp4' key:</span>
campers.has(<span class="hljs-string">'camp4'</span>);
<span class="hljs-comment">// output is `false`</span>
</code></pre>
<p>The <code>campers</code> Map does not currently have an element with a <code>'camp4'</code> key. Therefore, the <code>has('camp4')</code> function call will return <code>false</code>.</p>
<pre><code class="lang-js"><span class="hljs-comment">// If we add an element with the 'camp4' key to the map</span>
campers.set(<span class="hljs-string">'camp4'</span>, <span class="hljs-string">'Ana'</span>);

<span class="hljs-comment">// and try looking for that key again</span>
campers.has(<span class="hljs-string">'camp4'</span>);
<span class="hljs-comment">// output is `true`</span>
</code></pre>
<p>Since the map now does have an element with a <code>'camp4'</code> key, the <code>has('camp4')</code> function call will return <code>true</code> this time!</p>
<p>In a more real-world scenario, you might not manually add the elements to the Map yourself, so the <code>has()</code> function would become really useful in those cases.</p>
<h2 id="heading-mapprototypeforeach"><strong>Map.prototype.forEach</strong></h2>
<p>Executes the passed function on each key-value pair in the <code>Map</code> object. Returns <code>undefined</code>.</p>
<h2 id="heading-syntax-9"><strong>Syntax</strong></h2>
<pre><code class="lang-javascript">myMap.forEach(callback, thisArg)
</code></pre>
<h2 id="heading-parameters-4"><strong>Parameters</strong></h2>
<ul>
<li><strong>callback</strong> Function to execute for each element. </li>
<li><strong>thisArg</strong> Value to use as this when executing callback.</li>
</ul>
<h2 id="heading-example-9"><strong>Example</strong></h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
myMap.set(<span class="hljs-string">'foo'</span>,<span class="hljs-number">1</span>);
myMap.set(<span class="hljs-string">'bar'</span>,<span class="hljs-number">2</span>);
myMap.set(<span class="hljs-string">'baz'</span>,<span class="hljs-number">3</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">valueLogger</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${value}</span>`</span>);
}

myMap.forEach(valueLogger);
<span class="hljs-comment">// 1</span>
<span class="hljs-comment">// 2</span>
<span class="hljs-comment">// 3</span>
</code></pre>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create your own Santa Tracker with Gatsby and React Leaflet ]]>
                </title>
                <description>
                    <![CDATA[ The Christmas season is a magical time of year. We have Santa flying around spreading cheer and Elf roaming around New York during our yearly rewatch with family and friends. Buddy the Elf waving To get in the spirit, we’re going to spin up a web ap... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/</link>
                <guid isPermaLink="false">66b8e32047e3b55b9fb6ee41</guid>
                
                    <category>
                        <![CDATA[ Santa ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Christmas ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ holidays ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 11 Dec 2019 15:14:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/12/santa-tracker.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The Christmas season is a magical time of year. We have Santa flying around spreading cheer and Elf roaming around New York during our yearly rewatch with family and friends.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/elf-waving.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Buddy the Elf waving</em></p>
<p>To get in the spirit, we’re going to spin up a web app that includes a map that tracks Santa on it!</p>
<p><em>Edit 12/23: Updated the app to request directly to Santa's route, just in case the original API doesn't work as originally expected.</em></p>
<h2 id="heading-what-are-we-going-to-build"><strong>What are we going to build?</strong></h2>
<p>We’re going to work through building a mapping app that tracks Santa’s route and his current location.</p>
<p>To achieve this, we’re going to spin up a premade Gatsby starter that will give us a basic foundation for a map, utilize Google’s unofficial API to grab Santa’s route, and overlay his position and route on top of the map with Leaflet.</p>
<h2 id="heading-woah-a-mapping-app"><strong>Woah, a mapping app?</strong></h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/ay-caramba.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Ay Caramba</em></p>
<p>Yup. If you haven’t played with maps before, don’t be discouraged! It's not as bad as you probably think. If you’d rather start with mapping basics, you can <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">read more about how mapping works</a> first.</p>
<h2 id="heading-what-do-we-need-before-we-get-started"><strong>What do we need before we get started?</strong></h2>
<p>For this exercise, I’m going to assume you have <a target="_blank" href="https://nodejs.org/en/">node</a> or <a target="_blank" href="https://yarnpkg.com/en/">yarn</a> installed. For each example, I'll use yarn, but use the tool of your choice.</p>
<p>You’ll also want to install <a target="_blank" href="https://www.gatsbyjs.org/docs/gatsby-cli/">Gatsby’s CLI</a> globally which will allow us to use their <a target="_blank" href="https://www.gatsbyjs.org/docs/starters/">Starter tools</a>.</p>
<p>To set up Gatsby’s CLI, run the following command:</p>
<pre><code>yarn <span class="hljs-built_in">global</span> add gatsby-cli
</code></pre><p>After, you should be able to run <code>gatsby -h</code> to see the available commands, which means it’s successfully installed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/gatsby-help-install-verify.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Running gatsby -h to verify install</em></p>
<p>For more info about the Gatsby CLI, you can <a target="_blank" href="https://www.gatsbyjs.org/docs/gatsby-cli/">check out their documentation</a>.</p>
<h2 id="heading-getting-started-with-our-map-foundation"><strong>Getting started with our map foundation</strong></h2>
<p>Once our command line tools are set up, the first thing we’ll want to do is create a new Gatsby project using <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">a Leaflet starter</a> I put together. It provides us with a basic setup with <a target="_blank" href="https://leafletjs.com/">Leaflet</a> and <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a>.</p>
<p>Starting in your project directory, let’s install the project:</p>
<pre><code>gatsby <span class="hljs-keyword">new</span> [directory] https:<span class="hljs-comment">//github.com/colbyfayock/gatsby-starter-leaflet</span>
</code></pre><p>Make sure to replace <code>[directory]</code> with the location you want to set up your project.</p>
<p>Once you run that command, Gatsby will clone that project without any of the git references and install the packages required to start.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/installing-gatsby-starter-leaflet.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Installing Gatsby Starter Leaflet</em></p>
<p>To make sure it works, you can now navigate to that directory, spin up your server, and test it in the browser:</p>
<pre><code>cd [directory]
yarn develop
</code></pre><p>Where you see <code>[directory]</code> above, make sure to use the same path as you did before when setting up the new Gatsby project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/running-gatsby-starter-leaflet.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Running Gatsby Starter Leaflet</em></p>
<p>If all goes as planned, your server should start and you should now be able to see your basic mapping app in your browser!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/gatsby-starter-leaflet-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Gatsby Starter Leaflet in the browser</em></p>
<h2 id="heading-cleaning-things-up"><strong>Cleaning things up</strong></h2>
<p>This starter comes with a quick example of how we can interact with the map. We're not going to need this at all for our purposes so we can go ahead and clean things up.</p>
<p>To start, we’re going to open up our <code>index.js</code> file, the homepage file, and get rid of everything inside of the <code>mapEffect</code> function, which leaves us with:</p>
<pre><code class="lang-js"><span class="hljs-comment">// In src/pages/index.js</span>

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement } = {}</span>) </span>{
  <span class="hljs-comment">// Get rid of everything in here</span>
}
</code></pre>
<p>Now, let’s remove the <code>Marker</code> component nested inside of our <code>Map</code>, so we end up with:</p>
<pre><code class="lang-jsx">&lt;<span class="hljs-built_in">Map</span> {…mapSettings} /&gt;
</code></pre>
<p>Now that we’re no longer using that functionality, we can get rid of the variables and references at the top of the file, so you can go ahead and remove:</p>
<ul>
<li>useRef</li>
<li>promiseToFlyTo</li>
<li>getCurrentLocation</li>
<li>Marker</li>
<li>gatsby_astronaut</li>
<li>ZOOM</li>
<li>timeToZoom</li>
<li>timeToOpenPopupAfterZoom</li>
<li>timeToUpdatePopupAfterZoom</li>
<li>popupContentHello</li>
<li>popupContentGatsby</li>
<li>markerRef</li>
</ul>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracker/commit/58106bad98ff7491f56d580d01f70f1400120fce">Follow along with the commit.</a></p>
<h2 id="heading-finding-santa"><strong>Finding Santa</strong></h2>
<p>Now that we’re in a good place, let’s get our hands dirty and find Santa. To do this, we’re going to use Google’s unofficial, undocumented API. This means that it’s possible this API won’t be available the day after this get’s published, but let’s be optimistic.</p>
<p>Additionally, at the time of writing, it’s still showing last year’s destinations, so what we’re really going to be visualizing here is Santa’s previous year’s route, though the hope is this would reset on the 24th and we’ll all be merry!</p>
<p>Before we get Santa, let’s first add a line back to our <code>mapEffect</code> function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement } = {}</span>) </span>{
  <span class="hljs-keyword">if</span> ( !leafletElement ) <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>What this will do is prevent the rest of our code from running in the event our map isn't ready yet. The <code>mapEffect</code> function itself, as you can see in the <code>Map</code> component, runs inside of an instance of <code>useEffect</code> passing an argument of a <code>ref</code> to the map, allowing us to run some code after our component renders.</p>
<p>So once we have that line, let’s now fetch Santa’s route inside of our <code>mapEffect</code> function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement } = {}</span>) </span>{
  <span class="hljs-keyword">if</span> ( !leafletElement ) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">let</span> route, routeJson;
  <span class="hljs-keyword">try</span> {
    route = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://firebasestorage.googleapis.com/v0/b/santa-tracker-firebase.appspot.com/o/route%2Fsanta_en.json?alt=media&amp;2018b'</span>);
    routeJson = <span class="hljs-keyword">await</span> route.json();
  } <span class="hljs-keyword">catch</span>(e) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Failed to find Santa!: <span class="hljs-subst">${e}</span>`</span>);
  }
  <span class="hljs-built_in">console</span>.log(‘routeJson’, routeJson);
}
</code></pre>
<p>Let’s break this down:</p>
<ul>
<li>We grab Santa’s route via the API endpoint</li>
<li>Once we have his route, we grab the response in a JSON format to make it easier to work with</li>
<li>This is all wrapped in a try/catch so we can safely handle any response errors</li>
<li>Finally, we just <code>log</code> out our response for now</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/santas-route-object.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Santa's route object in the web console</em></p>
<p>Now we have Santa and his route, which means we can see all the destinations in his route. If you dig in the response a little bit, you can see some fun things like how many presents were delivered to each location and the weather at the time!</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracker/commit/f42c48fb0f0d70b4d20f1c2a1410bde1a4f27e84">Follow along with the commit.</a></p>
<h2 id="heading-put-a-pin-in-his-location"><strong>Put a pin in his location</strong></h2>
<p>We found Santa! ? Now let’s put him on the map.</p>
<p>For our purposes, we’ll need to find the latitude and longitude of Santa. The problem is, we don’t get this exact value defined anywhere, we just get his destinations.</p>
<p>Since we don’t have his location specified anywhere, we can utilize his last known location where presents were delivered. Add the following after our last snippet inside the <code>mapEffect</code> function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { destinations = [] } = routeJson || {};
    <span class="hljs-keyword">const</span> destinationsVisited = destinations.filter(<span class="hljs-function">(<span class="hljs-params">{arrival}</span>) =&gt;</span> arrival &lt; <span class="hljs-built_in">Date</span>.now());
    <span class="hljs-keyword">const</span> destinationsWithPresents = destinationsVisited.filter(<span class="hljs-function">(<span class="hljs-params">{presentsDelivered}</span>) =&gt;</span> presentsDelivered &gt; <span class="hljs-number">0</span>);
<span class="hljs-keyword">const</span> lastKnownDestination = destinationsWithPresents[destinationsWithPresents.length - <span class="hljs-number">1</span>]
</code></pre>
<p>Below our request code, we:</p>
<ul>
<li>Destructure <code>routeJson</code> to grab <code>destinations</code> into a constant, adding a fallback to an empty object</li>
<li>Filter the results to only find the destinations that he's visited, using the arrival time from the route object</li>
<li>Filter the results to find only the locations with presents</li>
<li>And finally grab the last item from the array, which shows his last known location</li>
</ul>
<p>At this point in time, 12/23, we don't actually have any destinations, as Santa is still at the North Pole. At any time, we can test this out to simulate a future date by replaceing <code>Date.now()</code> in <code>destinationsVisited</code> with a future date, such as <code>1577188980000</code> which would be around 7pm Eastern on 12/24. With that change, we can see what Santa's route actually looks like!</p>
<h2 id="heading-handle-a-missing-santa">Handle a missing Santa</h2>
<p>Now that it's close to Christmas, Santa will still be at the North Pole, so let's handle the case where we don't have a location.</p>
<p>Above the line where we set <code>lastKnownDestination</code>, let's add:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> ( destinationsWithPresents.length === <span class="hljs-number">0</span> ) {
  <span class="hljs-comment">// Create a Leaflet Market instance using Santa's LatLng location</span>
  <span class="hljs-keyword">const</span> center = <span class="hljs-keyword">new</span> L.LatLng( <span class="hljs-number">0</span>, <span class="hljs-number">0</span> );
  <span class="hljs-keyword">const</span> noSanta = L.marker( center, {
    <span class="hljs-attr">icon</span>: L.divIcon({
      <span class="hljs-attr">className</span>: <span class="hljs-string">'icon'</span>,
      <span class="hljs-attr">html</span>: <span class="hljs-string">`&lt;div class="icon-santa"&gt;?&lt;/div&gt;`</span>,
      <span class="hljs-attr">iconSize</span>: <span class="hljs-number">50</span>
    })
  });
  noSanta.addTo( leafletElement );
  noSanta.bindPopup( <span class="hljs-string">`Santa's still at the North Pole!`</span> );
  noSanta.openPopup();
  <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>Okay so what are we doing here?</p>
<ul>
<li>First, we’re checking if we have any destinations with presents, which here we don't</li>
<li>We first create a LatLng of the center of the map</li>
<li>We create a Leaflet marker, using that center, with a custom Icon of Santa</li>
<li>Next we add that Santa marker to the leafletElement, which is our map</li>
<li>To show a message, we first bind a popup with a custom message and open it</li>
<li>Finally we return so the rest of the code doesn’t run, as we don’t have Santa at this point</li>
</ul>
<p>This was a section added after published to handle the API resetting, but you can still follow along with the code I added in context of the rest of the rest of the code.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracker/blob/master/src/pages/index.js#L40">Follow along in the code.</a></p>
<h2 id="heading-pinning-santa">Pinning Santa</h2>
<p><em>Edit 12/23: This section was originally written with the previous year's API, but this is still a good example of what you'll expect on the response, so you can follow right along.</em></p>
<p>And as we can see, since we’re looking at last year’s data, Santa is back home at the North Pole.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/santas-last-known-destination-object.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Santa's last known location in the web console</em></p>
<p>With his location, we can pull that apart, set up a Leaflet marker instance, and add our old friend to the map. Add the following after our last snippet inside the <code>mapEffect</code> function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> santaLocation = <span class="hljs-keyword">new</span> L.LatLng( lastKnownDestination.location.lat, lastKnownDestination.location.lng );

<span class="hljs-keyword">const</span> santaMarker = L.marker( santaLocation, {
  <span class="hljs-attr">icon</span>: L.divIcon({
    <span class="hljs-attr">className</span>: ‘icon’,
    <span class="hljs-attr">html</span>: <span class="hljs-string">`&lt;div class=“icon-santa”&gt;?&lt;/div&gt;`</span>,
    <span class="hljs-attr">iconSize</span>: <span class="hljs-number">50</span>
  })
});

santaMarker.addTo(leafletElement);
</code></pre>
<p>Here we:</p>
<ul>
<li>Create a Leaflet LatLng instance with his location</li>
<li>Create a Marker instance with our newly created LatLng instance</li>
<li>Add our new Marker to the map</li>
</ul>
<p>If we refresh our page, you’ll have to zoom out and pan up a little bit, but we'll see Santa on the map!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/santa-on-the-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Santa on the map</em></p>
<p>Before we move on, let’s give Santa a little holiday cheer to make him easier to find. Find your <code>application.scss</code> file and toss these styles in:</p>
<pre><code class="lang-scss"><span class="hljs-comment">// In src/assets/stylesheets/application.scss</span>

<span class="hljs-selector-class">.icon</span> {

  &amp; &gt; <span class="hljs-selector-tag">div</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-attribute">overflow</span>: hidden;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">3px</span> <span class="hljs-number">4px</span> rgba(<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,.<span class="hljs-number">4</span>);
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">transition</span>: all .<span class="hljs-number">2s</span>;

    &amp;<span class="hljs-selector-pseudo">:hover</span> {
      <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">4px</span> <span class="hljs-number">8px</span> rgba(<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,.<span class="hljs-number">6</span>);
    }

  }

}

<span class="hljs-selector-class">.icon-santa</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">50px</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">50px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">3em</span>;
  <span class="hljs-attribute">background</span>: white;
}
</code></pre>
<p>This just adds a white circle around him, a little drop shadow, and increases the size a bit to make him a little easier to find on the map.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/santa-styled-on-the-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Santa styled on the map</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracker/commit/1b636107078fce64068ce661903892c095cb4668">Follow along with the commit.</a></p>
<h2 id="heading-drawing-his-route"><strong>Drawing his route</strong></h2>
<p>The last thing we’re going to do here is draw a path on the map showing his route so we can follow along.</p>
<p>To get started, let’s update our code and add this last bit after our last snippet in the <code>mapEffect</code> function:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Create a set of LatLng coordinates that make up Santa's route</span>

<span class="hljs-keyword">const</span> santasRouteLatLngs = destinationsWithPresents.map(<span class="hljs-function"><span class="hljs-params">destination</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> { location } = destination;
  <span class="hljs-keyword">const</span> { lat, lng } = location;
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> L.LatLng( lat, lng );
});

<span class="hljs-comment">// Utilize Leaflet's Polyline to add the route to the map</span>

<span class="hljs-keyword">const</span> santasRoute = <span class="hljs-keyword">new</span> L.Polyline( santasRouteLatLngs, {
  <span class="hljs-attr">weight</span>: <span class="hljs-number">2</span>,
  <span class="hljs-attr">color</span>: <span class="hljs-string">'green'</span>,
  <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">fillColor</span>: <span class="hljs-string">'green'</span>,
  <span class="hljs-attr">fillOpacity</span>: <span class="hljs-number">0.5</span>
});

<span class="hljs-comment">// Add Santa to the map!</span>

santasRoute.addTo(leafletElement);
</code></pre>
<p>What we’re doing:</p>
<ul>
<li>Creating an array of Leaflet LatLng instances that make up Santa’s route</li>
<li>Creating a Leaflet Polyline (a multi-point line) using that routes array</li>
<li>Make that Polyline green</li>
<li>Add our Polyline to the map</li>
</ul>
<p>What we get… is a bunch of squiggly lines!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/santas-route-on-the-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Santa's route on the map</em></p>
<p>This is expected. This gets technical really fast, but Leaflet by default can only understand 1 “portion” of the map as it wraps around in our browser. What this realistically means, is instead of drawing a line around a globe, the coordinates think it goes from one side of the world to the other as it hits the International Dateline. This is a bit out of scope for this tutorial, but you can check out <a target="_blank" href="https://github.com/briannaAndCo/Leaflet.Antimeridian">Leaflet.Antimeridian</a> to learn more and see if you can implement the solution to it.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracker/commit/3b0c08f066212ff32c82d3df2a13d1419da8ac41">Follow along with the commit.</a></p>
<h2 id="heading-a-few-quick-style-tweaks"><strong>A few quick style tweaks</strong></h2>
<p>One last thing! And this is completely optional. Let’s make the map a little bit bigger, set the background color to match our oceans, and zoom out a little bit. So let’s make a few changes:</p>
<pre><code class="lang-js"><span class="hljs-comment">// In src/pages/index.js</span>

<span class="hljs-keyword">const</span> DEFAULT_ZOOM = <span class="hljs-number">1</span>;
</code></pre>
<p>We’re setting our default zoom to <code>1</code> instead of <code>2</code> to allow the map to be zoomed out a bit.</p>
<pre><code class="lang-scss"><span class="hljs-comment">// In src/assets/stylesheets/pages/_home.scss</span>

<span class="hljs-selector-class">.page-home</span> {

  <span class="hljs-selector-class">.map</span>,
  <span class="hljs-selector-class">.map-base</span> {
    <span class="hljs-attribute">height</span>: <span class="hljs-number">80vh</span>;
  }

}
</code></pre>
<p>We’re setting our map to a height of <code>80vh</code> instead of <code>50vh</code> to make it take up a little more of our screen.</p>
<pre><code class="lang-scss"><span class="hljs-comment">// In src/assets/stylesheets/components/_map.scss</span>
<span class="hljs-selector-class">.map</span> {

  &amp;,
  <span class="hljs-selector-class">.map-base</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#acd3de</span>;
  }

}
</code></pre>
<p>We’re setting the background color of our map to <code>#acd3de</code> instead of <code>$blue-grey-50</code> which allows us to match the color of the oceans on our map.</p>
<p>What this achieves is being able to see Santa’s full route and Santa on the first view. Additionally, since the map only covers part of the screen, setting the background color of the map allows us to not have a little bit of a weird cutoff.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/santas-route-zoomed-out.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Santa's route zoomed out</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-santa-tracker/commit/882ea5c0b1b48da86d81494b8b4ad5db7bc1bae6">Follow along with the commit.</a></p>
<h2 id="heading-want-a-challenge"><strong>Want a challenge?</strong></h2>
<p>To take this 1 step further, follow along with both how we added the routes and Santa to the map and try to see if you can add a marker to each destination location to show where all of the stops are. Bonus, add a popup to each one that says how many presents were delivered to that location!</p>
<p>To see the answer with some code organization and how I added the gift markers, check out the final version of the <a target="_blank" href="https://github.com/colbyfayock/santa-tracker">Santa Tracker demo</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/final-santa-tracker-demo.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Final Santa Tracker demo</em></p>
<p>While you’re there, you can also see how I utilized Leaflet.Antimeridian to fix our map's route.</p>
<h2 id="heading-what-did-we-learn"><strong>What did we learn?</strong></h2>
<p>Building basic apps with a map isn’t nearly as bad as we thought! We learned how to fetch some data from an API, grab the data we need, and draw representations of that data on a map.</p>
<p>Next time you want to add a map widget to your landing page, try Leaflet. Share what you create on <a target="_blank" href="https://twitter.com/colbyfayock">Twitter</a>! Would love to see what you come up with.</p>
<p>I hope you and your family have a fantastic holiday season!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/happy-holidays-dunder-mifflin.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Happy Holidays from Dunder Mifflin</em></p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App in React with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter/">How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<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>
  </ul>
</div>

<p><em>Want to read some of my other articles? Check out my blog: <a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/</a></em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to build a mapping app in React the easy way with Leaflet ]]>
                </title>
                <description>
                    <![CDATA[ Mapping is hard, but spinning up a new app that renders maps doesn’t have to be. Here’s how you can easily get started working with maps in a new React app. Not that AAA map under your car seat Maps have been around for thousands of years, but they’v... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/</link>
                <guid isPermaLink="false">66b8e3249232d58aac300b11</guid>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 30 Oct 2019 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/10/mapping-with-leaflet.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Mapping is hard, but spinning up a new app that renders maps doesn’t have to be. Here’s how you can easily get started working with maps in a new React app.</p>
<h1 id="heading-not-that-aaa-map-under-your-car-seat">Not that AAA map under your car seat</h1>
<p>Maps have been around for thousands of years, but they’ve become more complex and powerful within the last couple decades simply due to the fact that computers exist. This has enabled the creation of products we use every day - like Google Maps that help us get home from work and avoid traffic, or weather maps that allow us to check real time radar images. Taking that a step further, scientists use maps every day using data from satellite imagery to try to get a better understanding of our humble planet.</p>
<p>This sounds hard…</p>
<h1 id="heading-building-maps">Building maps</h1>
<p>Plot twist, it’s not hard!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/plot-twist.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Final Space — What a twist!</em></p>
<p>At least it’s not hard to get started. Thankfully, the parts that are the hardest are already built into libraries that can easily be tapped into with JavaScript.</p>
<p>Enter Leaflet…</p>
<h1 id="heading-mapping-libraries">Mapping Libraries</h1>
<p>There are a few libraries in the mapping space right now (like <a target="_blank" href="https://openlayers.org/">OpenLayers</a>), but we like <a target="_blank" href="https://leafletjs.com/">Leaflet</a>.</p>
<p>To get started with Leaflet, first include the library’s assets on your page. Next, mount the application onto a root element within the DOM with some basic settings. You can kind of think of it like how React mounts to a DOM node, but Leaflet itself doesn’t use React. Once initialized, Leaflet allows you to start utilizing it’s API to project a basemap, add layers, tiles on those layers, and even start to draw on it.</p>
<h3 id="heading-basemap-layers-tiles">Basemap? Layers? Tiles?</h3>
<p>To get the basic gist, think of a cake. Traditionally, cakes have different layers, some on the bottom, some on the top, some might just cover one side with icing. Your map layers function similarly. The bottom layer, which is your foundation, will be your “basemap”. Below, we’re seeing a snapshot of the 2018 California Camp Fire wildfires on top of NASA’s <a target="_blank" href="https://terra.nasa.gov/about/terra-instruments/modis">MODIS Aqua</a> satellite imagery.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/modis-aqua-campfire-california-wildfires-1024x535.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>MODIS Aqua – California “Campfire” Wildfires</em></p>
<p>Now, to get a basemap, we need the imagery to produce it, which is where tiles come in. A tile is a single image block that makes up your group of tiles that represent your layer.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/modis-aqua-tms-tile-diagram-1024x535.jpg" alt="Image" width="600" height="400" loading="lazy">
_MODIS Aqua single tile and URI scheme – <a target="_blank" href="https://gibs-a.earthdata.nasa.gov/wmts/epsg3857/best/MODIS_Aqua_CorrectedReflectance_TrueColor/default/2018-11-08/EPSG3857_250m/8/97/41.jpg">Tile Link</a>_</p>
<p>Your tiles are really just a simple image, but alongside the rest, coordinated by geographic positions and zoom levels, make up what you see when you’re looking at a web map like the basemap shown above. The goal of including these smaller individual pieces rather than 1 huge image is that between dealing with the entire globe, the different zoom levels available, and the resolutions available beyond that, we’re talking about gigabytes upon gigabytes of image assets that just wouldn’t be reliable or realistic to serve as a whole.</p>
<p>Once you’ve established your basemap, you can then overlay additional layers using more imagery, vector tiles, or datapoints that get transformed to layers. In the screenshot below, we’re zoomed in beyond the highest resolution of our basemap. Notice though the imagery on the left, is an individual overlay tile from <a target="_blank" href="http://blog.digitalglobe.com/news/open-data-response-for-the-california-wildfires/">Digital Globe</a> that provides us with a higher resolution of part of the area surrounding the fire zone.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/modis-aqua-with-digital-globe-tile-1024x535.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>MODIS Aqua with tile overlay from Digital Globe</em></p>
<p>Another example on top of that is adding points representing fires collected from NASA’s <a target="_blank" href="https://earthdata.nasa.gov/earth-observation-data/near-real-time/download-nrt-data/viirs-nrt">VIIRS</a> imagery.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/modis-aqua-with-viirs-fire-data-1024x535.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>MODIS Aqua with VIIRS fire datapoint layer</em></p>
<p>This allows us to have the context of the basemap as well as being able to cast any type of data we’d like to better understand its effects.</p>
<p>In addition to the VIIRS data, there are many sources of imagery, vector tiles, and datasets published by governments and municipalities that you can use to help build interesting maps and data visualizations. NASA is one good source of these types of assets, but many commercial providers release <a target="_blank" href="https://www.digitalglobe.com/ecosystem/open-data">open access to disaster datasets</a> that help others build solutions around relief efforts.</p>
<h3 id="heading-whats-this-about-drawing-stuff">What’s this about drawing stuff?</h3>
<p>Usually when people use maps, they want to look at points of interest. Drawing gives us the ability to frame those areas of interest with different drawing tools such as creating a rectangle using a bounding box tool or drawing a circle. These are simple shapes, but those shapes represent a geographic space that can then be used to gather data about that area.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/bounding-box-alexadria-va-1024x535.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Rectangular bounding box around Alexandria, VA</em></p>
<h1 id="heading-react-leaflet">React ❤️ Leaflet</h1>
<p>Leaflet in itself gives you a lot to work with, but there’s still a lot of manual effort that goes along with it. If you’re used to building a React app, you’re probably not as used to building an entire UI using nothing but APIs based on the browser’s window, and this is where <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a> shines.</p>
<p>React Leaflet is a React library that takes the map building and bundles it into intuitive components that represents those parts of the map. Consider the above, where we talked about your basemap and layers to along with it, you might see it looking something along the lines of:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/map-component-code.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pseudo map component code</em></p>
<p>While you would probably expect that it’s not <em>as</em> flexible as utilizing the Leaflet APIs directly, this completely opens up one’s world to being able to easily spin up simple map solutions in an intuitive way without all the effort. After all, at that point, you’re spinning up a React app which you’re probably already familiar with.</p>
<h1 id="heading-taking-it-a-bit-further-with-gatsby">Taking it a bit further with Gatsby</h1>
<p>You want it easier, you say? You want me to build the map for you, you say? Well, you’re in luck! First, let’s give a brief introduction to another tool.</p>
<p>For the unfamiliar, <a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a> is a javascript framework that allows developers to easily spin up full, completely working React applications in a matter of minutes. They have all the nuts and bolts in place and moved out of the way to let you do what you do best: focus on the important parts of your application.</p>
<p>The beautiful part about Gatsby is that it supports extensions of their default installation which they call <em>Starters</em>. What better way to make it easier for people to spin up maps than to create a Gatsby Starter?</p>
<h1 id="heading-gatsby-starter-leaflet">Gatsby Starter Leaflet</h1>
<p>Combining the ease of a Gatsby Starter and the flexibility of Leaflet, we have <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Gatsby Starter Leaflet</a>. This simple tool allows you to scaffold a new React application running Leaflet along side React Leaflet in the matter of seconds (or minutes depending on your computer).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/gatsby-starter-leaflet-map-1024x535.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Starting page for Gatsby Starter Leaflet</em></p>
<p>With <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">a few basic commands</a>, including installing your dependencies, you have an app that’s ready for you to start building on top of to create maps that will save the world. Even better, it includes some out of the box integrations like <a target="_blank" href="https://www.openstreetmap.org/">OpenStreetMap</a> and an easy to setup map service configuration to the foundational React Leaflet component APIs that allow you to easily get product and have more flexibility to create smarter Mapping apps.</p>
<h1 id="heading-theres-gotta-be-some-downsides">There’s gotta be some downsides…</h1>
<p>No library or framework isn’t without its downsides. The more complicated your mapping application gets, the more pain points you run into. Here are a few from our experience that might help you settle in.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/bad-news.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Bob Kelso — Scrubs</em></p>
<h1 id="heading-leaflet-from-the-window-to-react">Leaflet — from the Window to React</h1>
<p>Trying to manage state and the lifecycle between your Leaflet map and your React components can prove to be tricky. Trying to constantly maintain and update your component using props will immediately start to create issues between stale map state or memory leaks due to maps not properly unmounting when the component does.</p>
<p><strong>Advice:</strong> mount your map with React, interact with it using the native Leaflet API. Once your map is rendered and settled down, you can use Leaflet to fly your user around the world and draw on your map without running into the state issues of multiple component renders.</p>
<h1 id="heading-limited-use-of-public-tiles">Limited Use of Public Tiles</h1>
<p>While there are a few tiling services available that allow you to easily plug in and create a basemap, not all of these are actually intended to be heavily used. Take for instance OpenStreetMap, while you may be able to play around and develop basic solutions on their public endpoint, heavy use will be throttled and potentially blocked without explicit permission from those who maintain their servers.</p>
<p><strong>Advice</strong>: when you’re just starting out playing around, you shouldn’t have to worry too much. Worst case the maps will be a little slow to download. As your application starts to get more traffic, you’ll want to look into <a target="_blank" href="https://github.com/Overv/openstreetmap-tile-server">spinning up your own tiling service</a> or paying for an out of the box solution such as <a target="_blank" href="https://www.mapbox.com/">Mapbox</a>.</p>
<h1 id="heading-get-mapping">Get mapping!</h1>
<p>It has never been easier to build a map-based web application. There is enough tooling, documentation, and public data available to help you get off the ground and start building maps to explore our world in the time it takes you to set up a blog or static website. So what are you waiting for?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/dora-explorer.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Go explore with Dora!</em></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>
  </ul>
</div>

<p><em>Originally published at <a target="_blank" href="https://www.element84.com/blog/mapping-with-leaflet-and-react">https://www.element84.com/blog/mapping-with-leaflet-and-react</a></em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to integrate maps in React Native using react-native-maps ]]>
                </title>
                <description>
                    <![CDATA[ By Mukhamed Khasanza Nowadays, almost all mobile applications have a maps feature. I had to integrate Google Maps to my React Native application, and the only choice was react-native-maps by Airbnb (it’s the only one still supported by the React Nati... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-integrate-maps-in-react-native-using-react-native-maps-5745490fe055/</link>
                <guid isPermaLink="false">66c352f1bc39b1419091be61</guid>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 07 Dec 2018 20:37:19 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*qp8QiCRmx0D041XU4qhx4g.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Mukhamed Khasanza</p>
<p>Nowadays, almost all mobile applications have a maps feature. I had to integrate Google Maps to my React Native application, and the only choice was react-native-maps by Airbnb (it’s the only one still supported by the React Native community).</p>
<p>I found several tutorials on how to set up this library, but none fully worked for me. This was because I had to run on both iOS and Android platforms and also support Google Maps for iOS.</p>
<p>Let’s create a React Native application from scratch using <strong>react-native-cli</strong> to show, step by step, how everything is installed. If you want to integrate react-native-maps for your existing app, skip <strong>Step 1</strong>.</p>
<h4 id="heading-step-1-install-and-set-up-react-native-application">Step 1: Install and set up React Native application</h4>
<p>If you haven’t installed the React Native command line interface, run: <code>npm install -g react-native-cli</code>. Now you can create your project, simply using: <code>react-native init ReactNativeMaps</code></p>
<p>Here are the dependency versions at the time of building this project:</p>
<ul>
<li>“react”: “16.6.1”</li>
<li>“react-native”: “0.57.5”</li>
<li>“react-native-maps”: “0.22.1” — we will install this one later.</li>
</ul>
<p>Now you can try to run your app, <code>react-native run-ios</code> or <code>react-native run-android</code> . Usually, this works without any problems.</p>
<h4 id="heading-step-2-add-and-link-react-native-maps-package">Step 2: Add and Link react-native-maps package</h4>
<p>Now let’s install react-native-map: <code>npm install --save react-native-maps</code> after installing the package you should link it to your native apps: <code>react-native link react-native-maps</code>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/UIyvyNDxVXBMQeYn9Wno72ob5T8iqR7Cr1c3" alt="Image" width="800" height="84" loading="lazy">
<em>You also got this? Cool, now we can continue.</em></p>
<h4 id="heading-step-3-set-up-apple-maps-ios">Step 3: Set up Apple Maps (iOS)</h4>
<p>It will be easier if we set them up separately by platform, so let’s first do it on iOS. Before integrating Google Maps, we will check if Apple Maps works correctly. Add the following code to your current rendering component where you want to render your MapView.</p>
<pre><code><span class="hljs-keyword">import</span> MapView <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-maps'</span>
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span>&lt;<span class="hljs-title">Props</span>&gt; </span>{  render() {    <span class="hljs-keyword">return</span> (      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MapView</span>        <span class="hljs-attr">style</span>=<span class="hljs-string">{{flex:</span> <span class="hljs-attr">1</span>}}        <span class="hljs-attr">region</span>=<span class="hljs-string">{{</span>          <span class="hljs-attr">latitude:</span> <span class="hljs-attr">42.882004</span>,          <span class="hljs-attr">longitude:</span> <span class="hljs-attr">74.582748</span>,          <span class="hljs-attr">latitudeDelta:</span> <span class="hljs-attr">0.0922</span>,          <span class="hljs-attr">longitudeDelta:</span> <span class="hljs-attr">0.0421</span>        }}        <span class="hljs-attr">showsUserLocation</span>=<span class="hljs-string">{true}</span>      /&gt;</span></span>    );  }}
</code></pre><p>You can test whatever location you want, just specify the appropriate Latitude and Longitude. As you can see, I enabled user location simply by adding the <code>showUserLocation</code> prop to the MapView component. If you are running on the real device you will see your current location.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/qtVkxY6KL4FhpwLUbEbBeqN8o6o7poi1ewRF" alt="Image" width="800" height="866" loading="lazy"></p>
<p>So, as you can see, by default Apple Maps is already working. More than that, if you linked everything correctly and enabled the user location, it’s actually done a lot of things for us (the user permission for the location with a default message). If you came from native iOS development, then you probably know what is an info.plist file.</p>
<h4 id="heading-step-4-install-cocoapods-and-googlemaps-package-ios">Step 4: Install Cocoapods and ‘GoogleMaps’ package (iOS)</h4>
<p>Apple Maps was easy, right? Agreed — so let’s see what Google Maps has for us. We have to install Google Maps SDK for iOS. We will use Cocoapods. If you haven’t used it before, run <code>sudo gem install cocoapods</code>.</p>
<p>Now you have to create a Podfile where you will specify the dependencies of your iOS application. Navigate to your iOS/ folder in your React Native app and run: <code>pod init</code> or you can use <code>touch Podfile</code> you should have something similar to this:</p>
<pre><code># platform :ios, <span class="hljs-string">'9.0'</span>
</code></pre><pre><code>target <span class="hljs-string">'ReactNativeMaps'</span> <span class="hljs-keyword">do</span>
</code></pre><pre><code># Pods <span class="hljs-keyword">for</span> ReactNativeMaps
</code></pre><pre><code>pod <span class="hljs-string">'GoogleMaps'</span>
</code></pre><pre><code>end
</code></pre><p>As you can see, I added the pod GoogleMaps and now we have to install it. If you are still on iOS/ folder, run: <code>pod install</code> . If you try to run it now, you will probably get an error:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/soaOtijGp-7CiGQVsNiwgljfHyLEQvrDJvEg" alt="Image" width="277" height="600" loading="lazy"></p>
<p>Okay, let’s do what it wants. Now we should open xCode workspace.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Vr6q4qYXaiFqnHdGtSNnhKSIZFqCMCFVeVEI" alt="Image" width="800" height="267" loading="lazy"></p>
<p>Navigate to AirGoogleMaps folder from node_modules/</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Taoc1pnk-dNBMzyAmjjE3CO8AkOm8t9KQhXf" alt="Image" width="800" height="241" loading="lazy"></p>
<p>And drag it to the top of your xCode project</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ewvVl0gCwzwrNj1gd3itRZnWJVPGOCiKkdSo" alt="Image" width="800" height="323" loading="lazy"></p>
<p>Please try to build your xCode project, if you are failing</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/6aQVp2Zl6gKnE6d3DdqMULm2WHmp70ws6QBE" alt="Image" width="800" height="286" loading="lazy"></p>
<p>You should add <code>HAVE_GOOGLE_MAPS=1</code>Preprocessor Macro to Build Settings</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/IhgPZQBomXmc4UKlP4ynYNIoU3Y0hlyGivGc" alt="Image" width="800" height="484" loading="lazy"></p>
<h4 id="heading-step-5-get-google-maps-api-key-run-ios-app-with-google-maps">Step 5: Get Google Maps API key, Run iOS app with Google Maps</h4>
<p>So now we have to generate a <a target="_blank" href="https://developers.google.com/maps/documentation/ios-sdk/get-api-key"><strong>Google Maps API key</strong></a><strong>.</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/dnmuyvL7Nd99BHxkK2F4iUCBbBeoypyPVfyw" alt="Image" width="800" height="253" loading="lazy"></p>
<p>Copy your API key and add to AppDelegate.m file.</p>
<p><code>#import &lt;GoogleMaps/GoogleMaps</code>.h&gt;</p>
<p><code>[GMSServices provideAPIKey:@"YOUR_API_KEY"]</code></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/oHeCkflMd3zznfYFMPBD6tglu4n9tfnoCghs" alt="Image" width="800" height="408" loading="lazy"></p>
<p>Now you can tell your MapView component that you are ready to use Google Maps.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/EojYRgWTNtO0zlMmicx0EVmv-0dBi22Y3Euf" alt="Image" width="800" height="636" loading="lazy"></p>
<p>Oh yesss, please run your iOS app. And you will get Google Maps.</p>
<p>I hope.</p>
<h4 id="heading-step-6-lets-try-android-now">Step 6: Let’s try Android now</h4>
<p>Okay now we can quit xCode and let’s just try <code>react-native run-android</code>. If you are getting the same as this:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/PZJ0vNEXuf1F-IUTAx0UAoJcW9rZy9V1FlbR" alt="Image" width="800" height="310" loading="lazy"></p>
<p>check your <strong>android/app/build.gradle</strong> file. And replace this:</p>
<p><code>compile project(':react-native-maps')</code> with this:</p>
<pre><code>implementation(project(<span class="hljs-string">':react-native-maps'</span>)){        exclude group: <span class="hljs-string">'com.google.android.gms'</span>, <span class="hljs-attr">module</span>: <span class="hljs-string">'play-services-base'</span>        exclude group: <span class="hljs-string">'com.google.android.gms'</span>, <span class="hljs-attr">module</span>: <span class="hljs-string">'play-services-maps'</span>    }implementation <span class="hljs-string">'com.google.android.gms:play-services-base:12.0.0'</span>implementation <span class="hljs-string">'com.google.android.gms:play-services-maps:12.0.0'</span>
</code></pre><p>Oh, and don’t forget to add API_KEY to AndroidManifest.xml file.</p>
<pre><code>&lt;application&gt;   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">meta-data</span>      <span class="hljs-attr">android:name</span>=<span class="hljs-string">"com.google.android.geo.API_KEY"</span>      <span class="hljs-attr">android:value</span>=<span class="hljs-string">"YOUR_API_KEY"</span>/&gt;</span></span>&lt;/application&gt;
</code></pre><p>Yes, now your app is running on both platforms. Please check the <a target="_blank" href="https://github.com/react-community/react-native-maps/blob/master/README.md"><strong>react-native-maps</strong></a> repo for more fun things that you can do with your MapView component.</p>
<h4 id="heading-conclusion">Conclusion</h4>
<p>Hope my first article on Medium was helpful for you. Please, if you see any mistakes don’t hesitate to leave a comment, I will appreciate your comments!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Total Ellipse on the Map ]]>
                </title>
                <description>
                    <![CDATA[ By Dalya Gartzman Or, how to choose the best way to walk to the beach after work It was a cool autumn evening when Hila Kloper and I were thinking of going to the beach after work. The beach is about 2.5Km away from the office. We were even consideri... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-total-ellipse-on-the-map-9e30d5235078/</link>
                <guid isPermaLink="false">66d45e00e39d8b5612bc0d9b</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Math ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 19 Nov 2018 21:26:26 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*4Di0P5E6_sQYXxYV.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Dalya Gartzman</p>
<h4 id="heading-or-how-to-choose-the-best-way-to-walk-to-the-beach-after-work">Or, how to choose the best way to walk to the beach after work</h4>
<p>It was a cool autumn evening when Hila Kloper and I were thinking of going to the beach after work. The beach is about 2.5Km away from the office.</p>
<p>We were even considering strolling down the streets of Tel Aviv, willing to stretch our path to 3Km, and thinking to ourselves “mmm we wonder how far this stretch can take us?”</p>
<p>Well, long story short, we didn’t go to the beach. Instead, we wrote a script that draws an ellipse around the office and the beach. The ellipse covers the city area we <em>may</em> go through if we ever decide to go to the beach after work.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Kpo6C3-boqp5qXw2eZlhoJsP10FM0kZhDnIv" alt="Image" width="463" height="499" loading="lazy">
<em>When developers want to do something fun outside and they end up writing a script about it instead.</em></p>
<h3 id="heading-its-the-ellipse-of-life">It’s the Ellipse of Life</h3>
<p><strong>Or - why should we care about ellipses?</strong></p>
<p>A circle is in some way the “natural” area around one point. An ellipse is the “natural” area around two points or a line. To name a few examples, <a target="_blank" href="https://en.wikipedia.org/wiki/Elliptic_orbit">bodies of mass move in elliptic orbits</a>, ellipses represent the <a target="_blank" href="https://en.wikipedia.org/wiki/Tissot%27s_indicatrix">distortion caused by projecting a 3D map on 2D</a>, and ellipses are also an accurate way to plot <a target="_blank" href="https://anitagraser.com/2018/09/04/plotting-gps-trajectories-with-error-ellipses-using-time-manager/">confidence of noisy GPS data</a> (and <a target="_blank" href="https://www.xarg.org/2018/04/how-to-plot-a-covariance-error-ellipse/">confidence areas in 2D data</a> in general).</p>
<p>In our case, we wanted to draw an area around the line starting at our office and ending at the beach. The easiest solution we found for <a target="_blank" href="https://gis.stackexchange.com/questions/243459/drawing-ellipse-with-shapely">drawing ellipses</a> involved <a target="_blank" href="https://pypi.org/project/Shapely/">shapely</a> and <a target="_blank" href="https://matplotlib.org/">pyplot.</a> It still required some modifications due to our GPS and map constraints.</p>
<p>So, if you are here because you are looking for an easy copy-pastable code that draws an ellipse on a map — you can go to <a target="_blank" href="https://github.com/DalyaG/CodeSnippetsForPosterity/tree/master/PlotEllipse">this repository</a> we made. If you are also interested to learn <strong>how</strong> we found the complete solution to our problem, you are welcome to join us for the ride. We rediscover elementary geometry, learn about coordinates systems, and play around with some math code.</p>
<h3 id="heading-girls-just-wanna-have-ellipses">Girls Just Wanna Have Ellipses</h3>
<blockquote>
<p><strong>Us:</strong> “Oh there must be a package somewhere that can draw an ellipse on a map!”<br><strong>The Internet:</strong> “No there isn’t.”<br><strong>Us:</strong> “But there must be a simple copy-pastable code somewhere!”<br><strong>Stackoverflow:</strong> “I have incomprehensible ones if you want.”<br><strong>Us:</strong> “Well, OK, we’ll take an hour and make one ourselves!”<br><strong>Reality:</strong> “…”</p>
</blockquote>
<p>Figuring out what an ellipse actually is was the first challenge.<br><a target="_blank" href="http://mathworld.wolfram.com/Ellipse.html">Wolfram Alpha</a> told us that an ellipse is the set of points that have the same sum-of-distances from two mutual centers. Or something like that. Wolfram Alpha can be rather cryptic sometimes. But they have a gif so that’s nice.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ubxw-BHnbWQyhC1gHYMoJV3BRDBG-2RUlr7I" alt="Image" width="274" height="137" loading="lazy">
<em>Ah… now that’s clear.</em></p>
<p>So all we have to do is make sure we have these inputs:</p>
<ul>
<li><code>p1, p2</code> - GPS coordinates.</li>
<li><code>r</code> - the radius which is actually the sum of distances from a point on the ellipse to the two centers.</li>
</ul>
<p>Then follow this plan:</p>
<ol>
<li>Find <code>a</code> and <code>b</code>, the axes of the ellipse.</li>
<li>Draw an ellipse around the origin <code>(0,0)</code> measured in meters.</li>
<li>Move the ellipse to the center between the input GPS locations.</li>
<li>Rotate according to the angle between the input GPS locations.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-970C4VzJQ2BxklnOsjfYlAp2MbeTUrmq-Mk" alt="Image" width="800" height="200" loading="lazy"></p>
<p>And that’s it.</p>
<p>Sounds simple enough, right?</p>
<h3 id="heading-the-long-and-winding-road-that-leads-to-ellipse">The Long and Winding Road (That Leads to Ellipse)</h3>
<h4 id="heading-step-1-find-the-axes">Step 1. Find the axes.</h4>
<p>Here we needed to do some basic Pythagorean algebra. This image from <a target="_blank" href="https://en.wikipedia.org/wiki/Ellipse">Wikipedia</a> was somewhat helpful:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/am1h1sbO6znf1TBZs-I-G2j6seQMYXDX12k5" alt="Image" width="296" height="229" loading="lazy"></p>
<p>Computing <code>c</code> from GPS coordinates was easy thanks to <a target="_blank" href="https://pypi.org/project/haversine/">haversine</a> package.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">GetEllipseAxisLengths</span>(<span class="hljs-params">p1_lat, p1_lng, p2_lat, p2_lng,
                          radius_in_meters</span>):</span>
    c2 = haversine((p1_lat, p1_lng), (p2_lat, p2_lng)) * <span class="hljs-number">1000.0</span>
    <span class="hljs-keyword">if</span> radius_in_meters &lt; c2:
        <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Please specify radius larger than the               
                          distance between the two input points."</span>)
    a = radius_in_meters / <span class="hljs-number">2.0</span>
    b = sqrt(pow(a, <span class="hljs-number">2</span>) - pow(c2 / <span class="hljs-number">2.0</span>, <span class="hljs-number">2</span>))
    <span class="hljs-keyword">return</span> a, b
</code></pre>
<h4 id="heading-step-2-draw-an-ellipse-around-the-origin">Step 2. Draw an Ellipse Around the Origin.</h4>
<p>What we did here is that we took evenly spaced points on the <code>x</code> axis and for each one found the two points on the ellipse that project to it:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/prw5iyWrz2XEn9FVkbcOvoF-VA-STwLSc1Oy" alt="Image" width="286" height="94" loading="lazy">
<em>Luckily we found this lovely equation on Wikipedia.</em></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">GetEllipsePointInMeters</span>(<span class="hljs-params">a, b, num_points</span>):</span>
    <span class="hljs-string">"""
    :param a: length of "horizontal" axis in meters
    :param b: length of "vertical" axis in meters
    :param num_points: (half the) number of points to draw
    :return: List of tuples of perimeter points on the ellipse, 
             centered around (0,0), in m.
    """</span>
    x_points = list(np.linspace(-a, a, num_points))[<span class="hljs-number">1</span>:<span class="hljs-number">-1</span>]
    y_points_pos = [sqrt(pow(a, <span class="hljs-number">2</span>) - pow(x, <span class="hljs-number">2</span>)) * 
                    (float(b) / float(a))
                    <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> x_points]
    y_points_neg = [-y <span class="hljs-keyword">for</span> y <span class="hljs-keyword">in</span> y_points_pos]

    perimeter_points_in_meters = 
        [tuple([-a, <span class="hljs-number">0</span>])] + \
        [tuple([x, y]) <span class="hljs-keyword">for</span> x, y <span class="hljs-keyword">in</span> zip(x_points, y_points_pos)] + \
        [tuple([a, <span class="hljs-number">0</span>])] + \
        list(reversed([tuple([x, y]) 
                       <span class="hljs-keyword">for</span> x, y <span class="hljs-keyword">in</span> zip(x_points, y_points_neg)]))
    <span class="hljs-keyword">return</span> perimeter_points_in_meters
</code></pre>
<h4 id="heading-step-3-how-do-you-even-add-meters-to-gps">Step 3. How Do You Even Add Meters to GPS?</h4>
<p>Well this was a tricky one, and the answer lies in understanding that</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Hc00Kw6PkLDTkU8eq7GYS6fj10fIP48qGltv" alt="Image" width="450" height="208" loading="lazy">
<em>Unleashing the secrets of elementary geometry.</em></p>
<blockquote>
<p>Fun fact: the Earth’s radius is around 6371000 meters on average!</p>
</blockquote>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">AddMetersToPoint</span>(<span class="hljs-params">center_lng, center_lat, dx, dy</span>):</span>
    <span class="hljs-string">"""
    :param center_lng, center_lat: GPS coordinates of the center  
           between the two input points.
    :param dx: distance to add to x-axis (lng) in meters
    :param dy: distance to add to y-axis (lat) in meters
    """</span>
    new_x = (center_lng + (dx / R_EARTH) * (<span class="hljs-number">180</span> / pi) /   
             np.cos(center_lat * pi/<span class="hljs-number">180</span>))
    new_y = center_lat + (dy / R_EARTH) * (<span class="hljs-number">180</span> / pi)
    <span class="hljs-keyword">return</span> tuple([new_x, new_y])
</code></pre>
<h4 id="heading-step-4-rotate">Step 4. Rotate.</h4>
<p>This time, the wonders of the internet did not fail us (as they did on our major ellipse-drawing task). We found <a target="_blank" href="https://pypi.org/project/Shapely/">shapely</a> package to do the rotation for us. The one trick to remember here is that you can’t rotate the points one by one. Rather you should <em>form a shape first</em>, and then <em>rotate the entire shape</em>.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">GetEllipsePoints</span>(<span class="hljs-params">p1_lat, p1_lng, p2_lat, p2_lng, 
                     perimeter_points_in_meters</span>):</span>
    <span class="hljs-string">"""
    Enter ellipse centers in lat-lng and ellipse perimeter points    
    around the origin (0,0), and get points on the perimeter of the 
    ellipse around the centers in lat-lng.
    :param p1_lat: lat coordinates of center point 1
    :param p1_lng: lng coordinates of center point 1
    :param p2_lat: lat coordinates of center point 2
    :param p2_lng: lng coordinates of center point 2
    :param perimeter_points_in_meters: List of tuples of perimeter 
           points on the ellipse, centered around (0,0), in m.
    :return: List of the points we really want, tuples of (lat,lng)
    """</span>
    center_lng = (p1_lng + p2_lng) / <span class="hljs-number">2.0</span>
    center_lat = (p1_lat + p2_lat) / <span class="hljs-number">2.0</span>
    perimeter_points_in_lng_lat = \
        [AddMetersToPoint(center_lng, center_lat, p[<span class="hljs-number">0</span>], p[<span class="hljs-number">1</span>])
         <span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> perimeter_points_in_meters]
    ellipse = LineString(perimeter_points_in_lng_lat)

    angle = degrees(atan2(p2_lat - p1_lat, p2_lng - p1_lng))
    ellipse_rotated = affinity.rotate(ellipse, angle)

    ellipse_points_lng_lat = list(ellipse_rotated.coords)
    ellipse_points = [tuple([p[<span class="hljs-number">1</span>], p[<span class="hljs-number">0</span>]]) 
                      <span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> ellipse_points_lng_lat]
    <span class="hljs-keyword">return</span> ellipse_points
</code></pre>
<h4 id="heading-surprise-step-5-draw-on-s2-map">Surprise! Step 5. Draw on s2 Map!</h4>
<p>We wanted to present the ellipse nicely on an <a target="_blank" href="http://s2map.com">s2map</a>. Apparently you can do that by opening the URL from inside your script. We used <a target="_blank" href="https://docs.python.org/2/library/subprocess.html">subprocess</a> to do that.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">OpenS2Map</span>(<span class="hljs-params">points</span>):</span>
    url = \
      <span class="hljs-string">"http://s2map.com/#order=latlng&amp;mode=polygon&amp;s2=false"</span> \
      <span class="hljs-string">"&amp;points={}"</span>.format(str(points).replace(<span class="hljs-string">" "</span>, <span class="hljs-string">","</span>))
    cmd = [<span class="hljs-string">"python"</span>, <span class="hljs-string">"-m"</span>, <span class="hljs-string">"webbrowser"</span>, <span class="hljs-string">"-t"</span>, url]
    subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                     stderr=subprocess.STDOUT).communicate()
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/OMCosB902DjSzC27OJcbQG3Z4UNQTBVq5LwC" alt="Image" width="800" height="498" loading="lazy">
<em>OK. can we go the beach now?</em></p>
<h3 id="heading-the-neighbors-ellipse-is-rounder">The Neighbor’s Ellipse Is Rounder</h3>
<p>You might notice our ellipse is not perfect. The points are evenly spaced on the axis between the centers, but they are not evenly spaced on the perimeter of the ellipse. The <code>GPS-&gt;meters-&gt;GPS</code> transformation might result in loss of meters here and there. But hey, done is better than perfect, and we have to leave something to do for the next time we want to go to the beach, right?</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A semi-automatic way to create your own grid map ]]>
                </title>
                <description>
                    <![CDATA[ By Krist Wongsuphasawat In the past year, the grid map style visualization has gained a lot of popularity in the US [2,4]. It has a quite a few nice properties, which inspired me to create one for Thailand. The rest of this article will explain grid ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/creating-grid-map-for-thailand-397b53a4ecf/</link>
                <guid isPermaLink="false">66c3481dfe2a6da72cef337a</guid>
                
                    <category>
                        <![CDATA[ D3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 12 Jan 2016 01:13:20 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*XFuuGyX5Ffi96DLWgupCtA.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Krist Wongsuphasawat</p>
<p>In the past year, the gr<em>id map</em> style visualization has gained a lot of popularity in the US [2,4]. It has a quite a few nice properties, which inspired me to create one for Thailand.</p>
<p>The rest of this article will explain grid maps, and how I created the grid map for Thailand map you see above.</p>
<p><strong>But if you are interested in using the map already without reading the details of how to create one yourself, jump straight to my <a target="_blank" href="https://github.com/kristw/gridmap-layout-thailand">gridmap-layout-thailand</a> github repository</strong>.</p>
<h4 id="heading-what-is-a-grid-map-and-what-are-its-properties">What is a Grid Map, and what are its properties?</h4>
<p>In a grid map, each region is represented as a tile of the equal shape and size. The tiles are placed to fit within a grid at positions that approximate real geographic position. If the tile is a square, the grid is rectangular. If the tile is a hexagon, then the grid is like a honeycomb. See the US maps below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ge3DyNssY0xnjHtgn0-Urg.png" alt="Image" width="800" height="181" loading="lazy">
_Maps of the US: (left) Hexagon Tile Grid Map (center) Square Tile Grid Map (right) Geographic Map. Source: [NPR Blog](http://blog.apps.npr.org/2015/05/11/hex-tile-maps.html" rel="noopener" target="<em>blank" title=")</em></p>
<p>Most of grid map visualizations are <a target="_blank" href="https://en.wikipedia.org/wiki/Choropleth_map"><em>choropleth maps</em></a> that use colors to encode values, such as amount of rainfall, average population age, or political alignment. Creating choropleth maps from geographic maps has some disadvantages, because the different sizes of each region introduce biases while interpreting the results. Also, many small regions are often too small to be notice on a map.</p>
<p><strong>Pros: g</strong>rid maps do not introduce biases due to different sizes of the regions, making it an interesting choice when creating a choropleth map. Small regions are now guaranteed to be big enough to be seen. It’s also easier to implement and faster to load than a geographic map.</p>
<p><strong>Cons:</strong> The positions of the regions are only approximations, and could be inaccurate. For example, some adjacent regions may not appear adjacent on the grid map. It also distorts the distance between regions.</p>
<h4 id="heading-creating-grid-map-for-thailand">Creating Grid Map for Thailand</h4>
<p>Here are the requirements:</p>
<ul>
<li>The overall map still looks similar to the geographical shape of Thailand. The neighboring regions should appear adjacent or close by.</li>
<li>Use square tiles for ease of curation and application. For example, this map can be drawn in Excel [3] or Google Sheets easily.</li>
<li>The map does not have any holes in the middle to avoid confusion.</li>
</ul>
<p>Of course, the most straightforward approach to create this map is to draw the map manually from scratch. However, I would like to save some energy with a semi-automatic approach:</p>
<ol>
<li>For each province, create one rectangle centered at its centroid.</li>
<li>Use a <a target="_blank" href="https://github.com/mbostock/d3/wiki/Force-Layout">force-directed simulation</a> to detect collisions between rectangles and remove overlaps. Each rectangle has its own center of gravity at the centroid of its province (<a target="_blank" href="http://bl.ocks.org/mbostock/1804919">multi-foci force-directed layout</a>). The solid lines in the figure below show displacements of the rectangles from their ideal positions.</li>
<li>Snap the rectangles to a rectangular grid.</li>
<li><a target="_blank" href="https://gist.github.com/kristw/31be36fa0df6a85c1cbd">Export results from Step 3 as CSV file</a> and manually curate in Google Sheets or Excel. The goal of this step is to remove unnecessary gaps, connect the map into one contiguous piece, and adjust the positions of some provinces.</li>
<li>Done! The new map only requires 40% of the original space.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*BRBbGurtiCLcUhM1P5kJYQ.png" alt="Image" width="799" height="497" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*2D2Pm7z5jxVxTepAe1JAkA.png" alt="Image" width="535" height="495" loading="lazy"></p>
<h4 id="heading-usage">Usage</h4>
<p>The output from this process can be used as JS, CSV or JSON files. Please see <a target="_blank" href="https://github.com/kristw/gridmap-layout-thailand">gridmap-layout-thailand</a> on GitHub for instructions. The code I used for steps 1–5 above are also in that repo.</p>
<p>Lastly, this method still depends a lot on manual curation at the end, which may not produce the best optimization. If you have any suggestions or would like to recommend a better approach, the comment box below is yours. :)</p>
<h4 id="heading-references">References</h4>
<p>[1] Mike Bostock. “<a target="_blank" href="http://bl.ocks.org/mbostock/1804919">Multi-Foci Force Layout</a>” <em>bl.ocks.org</em> Published 11 February 2012<br>[2] Danny DeBelius. “<a target="_blank" href="http://blog.apps.npr.org/2015/05/11/hex-tile-maps.html">Let’s Tesselate: Hexagons For Tile Grid Maps</a>” <em>NPR Blog.</em> Published 11 May 2015<br>[3] Caitlin Dempsey Morais. “<a target="_blank" href="http://www.gislounge.com/how-to-make-a-tile-grid-map-using-excel/">How to Make a Tile Grid Map Using Excel</a>” <em>GIS Lounge</em>. Published 10 November 2015<br>[4] Nathan Yau. “<a target="_blank" href="https://flowingdata.com/2015/05/12/the-great-grid-map-debate-of-2015/">The Great Grid Map Debate of 2015</a>” <em>Flowing Data.</em> Published 12 May 2015</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
