<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Gerard Hynes</title>
    <description>The latest articles on Forem by Gerard Hynes (@ger_hynes).</description>
    <link>https://forem.com/ger_hynes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F167600%2F747ff0de-4078-40fc-b409-524e6ca3668c.jpeg</url>
      <title>Forem: Gerard Hynes</title>
      <link>https://forem.com/ger_hynes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ger_hynes"/>
    <language>en</language>
    <item>
      <title>Resources for Learning Scala</title>
      <dc:creator>Gerard Hynes</dc:creator>
      <pubDate>Thu, 07 Apr 2022 16:27:57 +0000</pubDate>
      <link>https://forem.com/ger_hynes/resources-for-learning-scala-3cm2</link>
      <guid>https://forem.com/ger_hynes/resources-for-learning-scala-3cm2</guid>
      <description>&lt;p&gt;Recently, I've been learning Scala and when I first searched for resources for learners I was a bit worried by how few came up, and how many of them weren't very good. There were barely any YouTube tutorials, many of the blog posts were years old, and some of the conference talks required way more Mathematics than I had.&lt;/p&gt;

&lt;p&gt;Compared to languages like JavaScript or Python, or even Java, Scala is much more niche, with far less material for beginners. It also has its own quirks and a steeper learning-curve than some other programming languages, but Scala is definitely worth learning, and there are good resources out there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why learn Scala?
&lt;/h2&gt;

&lt;p&gt;A multi-paradigm language, Scala combines features of both object-oriented and functional programming. It runs on the Java Virtual Machine (JVM), and so can be used anywhere Java can run (it can even use Java libraries), but has a much more concise and “human readable” syntax.&lt;/p&gt;

&lt;p&gt;It's statically typed, so you'll catch more errors before you ship your code, and most of the time the compiler will infer the types for you so you don't need type annotations everywhere.&lt;/p&gt;

&lt;p&gt;Scala is especially used for high-performance distributed systems and large-scale data processing. Scala powers Twitter, DisneyPlus and The Guardian. Netflix, Spotify, and Amazon all use it for data analytics.&lt;/p&gt;

&lt;p&gt;If you want to learn Scala, here are some resources that I've found helpful. None of these links are affiliates, they're just resources that helped me on my learning journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scala at Light Speed
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KJerDdbC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/blfjdwnabazc9ok28thy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KJerDdbC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/blfjdwnabazc9ok28thy.png" alt="Scala at Light Speed" width="880" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://youtu.be/-8V6bMjThNo"&gt;https://youtu.be/-8V6bMjThNo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A two hour crash course introduction to the language by Daniel Ciocîrlan from &lt;a href="https://rockthejvm.com/"&gt;RocktheJVM&lt;/a&gt; that will give you a feel for whether you want to dive deeper into Scala. It does assume you have some familiarity with languages like Java, but Daniel's explanations are clear and the short course will quickly give you a good overview of the language, from the basic syntax to futures, pattern matching and higher order functions. From there, Daniel has many more videos on more advanced features of Scala, as well as tools and libraries like Akka, Cats and Doobie.&lt;/p&gt;

&lt;h3&gt;
  
  
  Effective Programming in Scala
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Sl6p2HM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0lphph9qz94wtdqpkcgp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Sl6p2HM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0lphph9qz94wtdqpkcgp.png" alt="Effective Programming in Scala" width="880" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://www.coursera.org/learn/effective-scala"&gt;https://www.coursera.org/learn/effective-scala&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you'd like a more thorough course with a college-semester like structure, this is a good option. Provided by the École Polytechnique Fédérale de Lausanne (which operates the &lt;a href="https://scala.epfl.ch/"&gt;Scala Center&lt;/a&gt; open source foundation), this Coursera course regularly opens for new enrollments and doesn't cost anything to audit. The lectures are clear and concise, explaining concepts in bite-sized stages. While the assignments can be a bit of a jump compared to the lecture content, the regular quizzes will help you retain what you're learning.&lt;/p&gt;

&lt;p&gt;The course uses Scala 3 (which is still very new) but the instructors give examples in Scala 2 where the syntax is different. The course also forms the first part of Coursera's &lt;a href="https://www.coursera.org/specializations/scala"&gt;Functional Programming in Scala Specialization&lt;/a&gt;, so if you want to take your learning further, there's a clear curriculum ahead of you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Written Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Official Scala Docs
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hkCVCAob--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z7dxffh4iyrg57wq7n5f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hkCVCAob--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z7dxffh4iyrg57wq7n5f.png" alt="The official Scala docs" width="880" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://docs.scala-lang.org/"&gt;https://docs.scala-lang.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The official documentation for languages isn't always accessible for learners, but the Scala docs are genuinely great: detailed, well-designed and written in pretty accessible language. The &lt;a href="https://docs.scala-lang.org/overviews/scala-book/introduction.html"&gt;Scala Book&lt;/a&gt; provides a friendly introduction and overview of the language in about 50 lessons.&lt;/p&gt;

&lt;h3&gt;
  
  
  Daniela Sfregola, Get Programming with Scala
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eA9Ajado--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wh0eqn4s0q3fegcxoaxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eA9Ajado--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wh0eqn4s0q3fegcxoaxl.png" alt="Get Programming with Scala" width="880" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://www.manning.com/books/get-programming-with-scala"&gt;https://www.manning.com/books/get-programming-with-scala&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Too many Scala resources assume two things: that you are already an experienced Java developer and that you are comfortable with university-level mathematics. Daniela Sfregola's excellent book assumes neither. It's written in a very accessible style with short chapters, exercises and projects to practice what you're learning. It's also very comprehensive, covering everything from getting started with sbt, the Scala build tool, and going over object-oriented and functional programming, to setting up a HTTP server, handling concurrency, serializing JSON and testing with ScalaTest.&lt;/p&gt;

&lt;h3&gt;
  
  
  This Week in Scala
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tnZaGLen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/opp08qgenuaz2vukuf51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tnZaGLen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/opp08qgenuaz2vukuf51.png" alt="This Week in Scala" width="880" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://medium.com/disney-streaming/tagged/scala"&gt;https://medium.com/disney-streaming/tagged/scala&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This newsletter by Petr Zapletal, Principal Engineer at Disney Streaming, aims to share the latest news from the world of Scala. While it does recommend learning resources, it's mostly a handy way to keep an eye on developments in the Scala ecosystem and learn about how the language is used in industry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practice
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Exercism
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qAOGkska--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuw5blyzs7s52p3r88eh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qAOGkska--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuw5blyzs7s52p3r88eh.png" alt="Exercism Scala Track" width="880" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://exercism.org/tracks/scala"&gt;https://exercism.org/tracks/scala&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There aren't a lot of resources that let you practice your Scala skills with exercises, which makes Exercism's Scala track particularly valuable. There are more than 90 challenges, which you solve locally, run tests on, and push your solutions to Exercism to share with other learners. The difficulty levels ramps up quite quickly from “Hello World” to solving tricky mathematical problems by making use of the ins and outs of the language.&lt;/p&gt;

&lt;p&gt;The ability to look at solutions by other learners is especially helpful, often revealing a much simpler or more efficient solution than the one you came up with. I haven't used their volunteer mentoring feature yet but the opportunity to give and receive one-on-one feedback sounds really promising.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forums
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scala Users
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bwdiCXBN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xxbss52ruyjtg0sbb5hu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bwdiCXBN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xxbss52ruyjtg0sbb5hu.png" alt="Scala Users" width="880" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://users.scala-lang.org/"&gt;https://users.scala-lang.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The official Scala forum. It's mostly used by experienced Scala developers but I've found the community to be generally quite friendly and willing to answer questions from learners.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scala Subreddit
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mEHecJ7k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6cpz2xdw8fks5i03e7v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mEHecJ7k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6cpz2xdw8fks5i03e7v.png" alt="Scala subreddit" width="880" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://www.reddit.com/r/scala/"&gt;https://www.reddit.com/r/scala/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As with any subreddit, this can have its share of strong opinions and arguments about things that really aren't important, but you can also find useful recommendations and sometimes answers to your very specific problems.&lt;/p&gt;

&lt;p&gt;If you're learning Scala, good luck and I hope you find these resources helpful.&lt;/p&gt;

</description>
      <category>scala</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How To Overcome CORS with Serverless Functions</title>
      <dc:creator>Gerard Hynes</dc:creator>
      <pubDate>Wed, 01 Sep 2021 14:41:21 +0000</pubDate>
      <link>https://forem.com/ger_hynes/how-to-overcome-cors-with-serverless-functions-am7</link>
      <guid>https://forem.com/ger_hynes/how-to-overcome-cors-with-serverless-functions-am7</guid>
      <description>&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Recently I was working on a &lt;a href="https://www.frontendmentor.io/challenges/ip-address-tracker-I8-0yYAH0" rel="noopener noreferrer"&gt;Frontend Mentor challenge&lt;/a&gt;, an app where you can input an IP address or url and fetch and display information about it.&lt;/p&gt;

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

&lt;p&gt;Things were going well. I got the layout sorted, I set up a custom map using React Leaflet and Mapbox.&lt;/p&gt;

&lt;p&gt;When it was time to fetch the data from the API, however, I ran into problems.&lt;/p&gt;

&lt;p&gt;Frontend Mentor had suggested using the &lt;a href="https://geo.ipify.org/" rel="noopener noreferrer"&gt;IP Geolocation API by IPify&lt;/a&gt; to get information based off an IP address or domain.&lt;/p&gt;

&lt;p&gt;If you sign up for a free account with IPify and paste &lt;code&gt;https://geo.ipify.org/api/v1?apiKey=YOUR_API_KEY&lt;/code&gt; into your url bar, it'll send back JSON with information about your IP address, your location, and your ISP provider.&lt;/p&gt;

&lt;p&gt;But if you try to make a HTTP request to this API from your client-side code, you'll get a message about CORS.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  What is CORS?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" rel="noopener noreferrer"&gt;CORS (Cross Origin Resource Sharing)&lt;/a&gt; is a mechanism that uses HTTP headers to give a browser permission to access resources from a server that's different from the server of the website making the request.&lt;/p&gt;

&lt;p&gt;It exists for a very good reason: &lt;strong&gt;security&lt;/strong&gt;. You don't want some random website to be able to ping your server and get sensitive data from it. To prevent this, browsers restrict cross-origin HTTP requests initiated from client-side scripts by default.&lt;/p&gt;

&lt;p&gt;You need to specify which urls can access data from your server by making sure the correct CORS headers get sent with each request. But you can't just change the CORS settings on someone else's server because that would defeat the whole point of CORS as a security layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  CORS Proxies
&lt;/h3&gt;

&lt;p&gt;The solution that most resources recommended is to use a proxy, another server that will receive the request from your browser, pass it on to the server you're trying to access, and then pass that server's response back to you. This way the entire request response process occurs server-side and isn't subject to CORS.&lt;/p&gt;

&lt;p&gt;There are a number of CORS proxies you can use, such as &lt;a href="https://corsproxy.github.io/" rel="noopener noreferrer"&gt;crossorigin.me&lt;/a&gt; or &lt;a href="https://cors-anywhere.herokuapp.com/corsdemo" rel="noopener noreferrer"&gt;CORS Anywhere&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But I didn't want to rely on a third-party proxy. After all, they can see all the data that you pass to them and could stop working at any time. I also didn't want to run and manage my own Node app just to act as a proxy.&lt;/p&gt;

&lt;p&gt;While doing some research, I came across a blog post by Jim Nielsen about &lt;a href="https://blog.jim-nielsen.com/2020/a-cors-proxy-with-netlify/" rel="noopener noreferrer"&gt;setting up a CORS proxy with Netlify&lt;/a&gt; that promised to solve CORS issues using Netlify redirects without having to run your own proxy server or rely on some random one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redirects
&lt;/h3&gt;

&lt;p&gt;Using redirect rules to proxy to an external service is something that Netlify actively supports. For example, you can set things up so that any requests to &lt;code&gt;/api/search&lt;/code&gt; will be redirected to &lt;code&gt;https://api.example.com/search&lt;/code&gt;. The &lt;a href="https://docs.netlify.com/routing/redirects/rewrites-proxies/" rel="noopener noreferrer"&gt;Netlify docs&lt;/a&gt; explain how to do it.&lt;/p&gt;

&lt;p&gt;You can set redirect rules in a &lt;code&gt;_redirects&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/api/*  https://api.example.com/:splat  200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or you can include them in your &lt;code&gt;netlify.toml&lt;/code&gt; file which sets the configuration for your entire app on Netlify.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[redirects]]
  from = "/api/*"
  to = "https://api.example.com/:splat"
  status = 200
  force = true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to test this out locally before deploying it, &lt;a href="https://www.netlify.com/products/dev/" rel="noopener noreferrer"&gt;Netlify Dev&lt;/a&gt; lets you run Netlify locally on your machine.&lt;/p&gt;

&lt;p&gt;Armed with this information, I added the redirects rules to my &lt;code&gt;netlify.toml&lt;/code&gt; file, ran the &lt;code&gt;netlify dev&lt;/code&gt; command and it worked!&lt;/p&gt;

&lt;p&gt;Relieved to be making progress, I deployed the app to Netlify... and ran into a new issue.&lt;/p&gt;

&lt;p&gt;Everything worked locally but once the app was deployed I kept getting a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502" rel="noopener noreferrer"&gt;502 Bad Gateway&lt;/a&gt; response, meaning that the proxy server received an invalid response from the server it was proxying to.&lt;/p&gt;

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

&lt;p&gt;Netlify have really great &lt;a href="https://answers.netlify.com/" rel="noopener noreferrer"&gt;Support Forums&lt;/a&gt; and the good people there pointed me to potential solutions - setting specific headers on my redirects, checking for differences between my local environment and the build environment on Netlify. But none of this made a difference.&lt;/p&gt;

&lt;p&gt;A Netlify engineer was able to confirm that the problem was that the API was not responding to the request within 30 seconds. For proxy rewrites, Netlify closes the connection in 30 seconds and since the request wasn't complete by then, it returns a 502. They suggested I move my code into a serverless function and see if that would resolve the issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution - Serverless Functions
&lt;/h3&gt;

&lt;p&gt;Serverless functions let you write server-side code that can work like an API endpoint, run automatically in response to events, or process complex jobs in the background, all without managing your own server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.netlify.com/products/functions/" rel="noopener noreferrer"&gt;Netlify Functions&lt;/a&gt; make setting up and running serverless functions pretty straightforward.&lt;/p&gt;

&lt;p&gt;You create a &lt;code&gt;functions&lt;/code&gt; directory in the root of your project and, inside that, a javascript file with the name of your function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;base-directory/
|- package.json
|- node_modules
|- functions/
   hello.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the function's file, you export an async handler function which returns a status code and a body. These functions can carry out tasks such as fetching data from an API, sending automated emails, or validating user input, before sending back a response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, to call a serverless function you make a request to &lt;code&gt;.netlify/functions/your-serverless-function&lt;/code&gt;. But you can also use redirects in your &lt;code&gt;netlify.toml&lt;/code&gt; to make this more concise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[build]
  functions = "functions"

[[redirects]]
  from = "/api/*"
  to = "/.netlify/functions/:splat"
  status = 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, requests to &lt;code&gt;/api/hello&lt;/code&gt; will be the same as &lt;code&gt;.netlify/functions/hello&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing Requests
&lt;/h3&gt;

&lt;p&gt;I moved the API request into a serverless function, ran Netlify Dev, and was immediately able to get back IP information.&lt;/p&gt;

&lt;p&gt;But for this particular project, I needed to be able to vary the requests I sent to the API.&lt;/p&gt;

&lt;p&gt;A request to &lt;code&gt;https://geo.ipify.org/api/v1?apiKey=YOUR_API_KEY&lt;/code&gt; will send back information about the IP address that sent the request.&lt;/p&gt;

&lt;p&gt;On the other hand, a request to &lt;code&gt;https://geo.ipify.org/api/v1?apiKey=YOUR_API_KEY&amp;amp;ipAddress=SOME_IP_ADDRESS&lt;/code&gt; will return information about the specified IP address.&lt;/p&gt;

&lt;p&gt;And finally, a request to &lt;code&gt;https://geo.ipify.org/api/v1?apiKey=YOUR_API_KEY&amp;amp;domain=SOME_DOMAIN&lt;/code&gt; will return information about that domain.&lt;/p&gt;

&lt;p&gt;But how was I going to pass this data to the serverless function?&lt;/p&gt;

&lt;p&gt;Well, thankfully, Ben Hong has a helpful tutorial on &lt;a href="https://explorers.netlify.com/learn/up-and-running-with-serverless-functions/customizing-the-request-with-serverless-functions" rel="noopener noreferrer"&gt;customizing the request with serverless functions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basically, I used fetch to make a POST request to the serverless function, passing the search input's value as the body of the request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/getIpInfo`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ipAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ipInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the serverless function, I extracted the search term from the body, used &lt;a href="https://github.com/validatorjs/validator.js/" rel="noopener noreferrer"&gt;validator.js&lt;/a&gt; to check if it was an IP address or domain, and appended it to the API endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// getIpInfo.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;validator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eventBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Check for IP Address or domain&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventBody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eventBody&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isIP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;amp;ipAddress=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;amp;domain=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed fetching data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Success! Thanks to serverless functions, my app can now make requests to the IP Geolocation API from the browser without running into any CORS issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try It Yourself
&lt;/h3&gt;

&lt;p&gt;If you are running into CORS issues when making HTTP requests from the browser, try proxying via redirects and, if that doesn't work for you, there's never been a better time to learn about serverless functions.&lt;/p&gt;

&lt;p&gt;Ben Hong's &lt;a href="https://explorers.netlify.com/learn/up-and-running-with-serverless-functions" rel="noopener noreferrer"&gt;Up and Running with Serverless Functions&lt;/a&gt; is a great place to get started.&lt;/p&gt;

&lt;p&gt;The code for my project is available on &lt;a href="https://github.com/gerhynes/ip-address-tracker" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. You can also try out the &lt;a href="https://goofy-spence-1d3ac9.netlify.app/" rel="noopener noreferrer"&gt;deployed app&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ania Kubów, &lt;a href="https://www.youtube.com/watch?v=n_KASTN0gUE" rel="noopener noreferrer"&gt;Create your first Netlify Serverless Function!&lt;/a&gt; - YouTube&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ben Hong, &lt;a href="https://explorers.netlify.com/learn/up-and-running-with-serverless-functions" rel="noopener noreferrer"&gt;Up and Running with Serverless Functions&lt;/a&gt; - Jamstack Explorers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" rel="noopener noreferrer"&gt;Cross-Origin Resource Sharing (CORS)&lt;/a&gt; - MDN Web Docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jim Nielsen, &lt;a href="https://blog.jim-nielsen.com/2020/a-cors-proxy-with-netlify/" rel="noopener noreferrer"&gt;Setup a CORS Proxy With Netlify&lt;/a&gt; - jim-nielsen.com&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Phil Hawksworth, &lt;a href="https://explorers.netlify.com/learn/exploring-netlify-redirects" rel="noopener noreferrer"&gt;Exploring Netlify Redirects&lt;/a&gt; - Jamstack Explorers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cors</category>
      <category>serverless</category>
      <category>netlify</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>How to Get Unstuck When Following a Programming Tutorial</title>
      <dc:creator>Gerard Hynes</dc:creator>
      <pubDate>Thu, 29 Jul 2021 15:14:38 +0000</pubDate>
      <link>https://forem.com/ger_hynes/3-steps-to-get-unstuck-when-following-a-programming-tutorial-1fcl</link>
      <guid>https://forem.com/ger_hynes/3-steps-to-get-unstuck-when-following-a-programming-tutorial-1fcl</guid>
      <description>&lt;p&gt;You know the feeling, right? You're following a programming tutorial, pouring new knowledge and skills into your head. Life is good. And then, suddenly, it's not.&lt;/p&gt;

&lt;p&gt;Something breaks. Your screen is covered in a less-than-helpful error message, your terminal is printing warnings about things you've never heard of, and your code has fallen over in a heap.&lt;/p&gt;

&lt;p&gt;Even with the most well-paced and clear tutorials, you will get stuck. I still do, all the time.&lt;/p&gt;

&lt;p&gt;It's frustrating, but it's not the end of the world. It might not feel like it, but it can be a great opportunity to learn.&lt;/p&gt;

&lt;p&gt;With experience, I've gotten better at getting unstuck, and I'd like to share a few methods I've collected for pushing through these challenges and getting back on track.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read, Search, Ask
&lt;/h3&gt;

&lt;p&gt;I've learned debugging tips from a wide range of sources but the foundation of my process for getting unstuck comes from freeCodeCamp's &lt;a href="https://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck-coding/19514" rel="noopener noreferrer"&gt;Read, Search, Ask methodology&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When you get stuck, their advice is to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the documentation or error&lt;/li&gt;
&lt;li&gt;Search Google&lt;/li&gt;
&lt;li&gt;Ask your friends for help&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a good strategy for three reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It will minimize the amount of time you spend stuck,&lt;/li&gt;
&lt;li&gt;It will maximize your chance of learning from the problem,&lt;/li&gt;
&lt;li&gt;It will help you to be respectful of other people's time when you ask them for help.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is still the core of my process for getting unstuck but I want to expand on what exactly I do when I &lt;strong&gt;Read&lt;/strong&gt;, &lt;strong&gt;Search&lt;/strong&gt; and &lt;strong&gt;Ask&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Read
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Read the Error Message
&lt;/h4&gt;

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

&lt;p&gt;Is there an error message yelling at you? Great! It might not seem it, but error messages are there to help you. It would be worse if your code just failed silently and left you none the wiser.&lt;/p&gt;

&lt;p&gt;Yes, sometimes error messages will be totally unhelpful, giving you no more information than "something went wrong". But other times the error message will point you on your way. If you see &lt;code&gt;TypeError: Cannot read property ‘length’ of undefined&lt;/code&gt;, check the variable that's showing up as undefined.&lt;/p&gt;

&lt;p&gt;Look at the filename and line number and see what's going on there. But, bear in mind, where your code crashed is where the error happened, not necessarily where the problem was first introduced. Maybe the error happened in your &lt;code&gt;getUsers()&lt;/code&gt; function, but the problem started in a &lt;code&gt;checkAuthentication()&lt;/code&gt; function that then called &lt;code&gt;getUsers()&lt;/code&gt;. Follow the call stack and see how far you can get.&lt;/p&gt;

&lt;p&gt;If the error message contains things you don't understand, don't panic, that's when you turn to Google (more on this below).&lt;/p&gt;

&lt;h4&gt;
  
  
  Read Your Code
&lt;/h4&gt;

&lt;p&gt;Sometimes it feels like 90% of bugs are caused by one character being wrong; a typo in a variable or function name, a missing closing parentheses or bracket. Look for these. Extensions like &lt;a href="https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer" rel="noopener noreferrer"&gt;Bracket Pair Colorizer&lt;/a&gt; can make this easier to spot.&lt;/p&gt;

&lt;p&gt;If the code you can see looks ok, try to surface the values that aren't immediately visible. Maybe a value is updating in the UI but isn't getting saved to the database. Drop a &lt;code&gt;console.log()&lt;/code&gt; into both your frontend and backend code. If the value changed, or failed to change, at some point, work backwards and try to find where the disconnect happened.&lt;/p&gt;

&lt;h4&gt;
  
  
  Read the Instructor's Code
&lt;/h4&gt;

&lt;p&gt;It's always helpful when an instructor provides a GitHub repo or includes downloadable files. If you have this, open it up and start comparing your code and theirs.&lt;/p&gt;

&lt;p&gt;Download their code and open it in your editor. Sometimes seeing their code with the same syntax highlighting as yours can help to make the differences stand out. &lt;a href="https://www.diffchecker.com/" rel="noopener noreferrer"&gt;Diffchecker&lt;/a&gt; is also useful when you're comparing two versions of the same code line by line.&lt;/p&gt;

&lt;p&gt;Narrow down the amount of code you need to read. Comment out all the code you just wrote. Uncomment it step by step and see when it breaks again. If you're working with components, comment out every component and gradually reintroduce them. Maybe it was the &lt;code&gt;Header&lt;/code&gt; rather than the &lt;code&gt;RegistrationForm&lt;/code&gt; that was causing the problem.&lt;/p&gt;

&lt;h4&gt;
  
  
  Read the Documentation
&lt;/h4&gt;

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

&lt;p&gt;When you're learning a technology for the first time, going from a tutorial to the docs can feel like diving into the deep end. Not all docs are well written or organized. Not all docs have good search functionality. But this is where a lot of your learning will happen.&lt;/p&gt;

&lt;p&gt;Reading the docs forces you to try to understand the technology you're using rather than just passively copying the tutorial. This is harder but also much more beneficial.&lt;/p&gt;

&lt;p&gt;The docs are a lifesaver when the syntax or the API has changed since the tutorial was created. You could have banged your head on the keyboard for hours but it turns out that you just need to change &lt;code&gt;if (process.browser)&lt;/code&gt; to &lt;code&gt;if (typeof window !== "undefined")&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Check which version of a library or framework the tutorial was using. If version 3.0 has replaced version 2.0, look for a &lt;strong&gt;migration guide&lt;/strong&gt; to help you get your code up to date. Now you'll not just have a working project again, but you'll have a better understanding of the underlying tools and technologies.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Search
&lt;/h3&gt;

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

&lt;p&gt;Ok, you've read your code, the instructor's code and the docs. Time to turn to Google.&lt;/p&gt;

&lt;p&gt;Thankfully, you are almost certainly not the first person to run into this specific problem. If a technology has existed long enough for there to be tutorials, then other people have already run into problems with it and written questions and answers that you can find.&lt;/p&gt;

&lt;p&gt;Don't feel guilty about googling. Every developer does it, from newbies to veterans.&lt;/p&gt;

&lt;p&gt;Colt Steele has a great video on &lt;a href="https://www.youtube.com/watch?v=LW9pT246LrI" rel="noopener noreferrer"&gt;The Google History of a High-Paid Senior Engineer&lt;/a&gt; which shows how often skilled and knowledgeable engineers google even basic concepts.&lt;/p&gt;

&lt;p&gt;Googling is a skill that you will develop with time and practice. There's a useful post from Juan Cruz Martinez on &lt;a href="https://betterprogramming.pub/11-tricks-to-master-the-art-of-googling-as-a-software-developer-2e00b7568b7d" rel="noopener noreferrer"&gt;how to get better at googling as a developer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here, I'll focus on four ways to search more effectively:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Be as specific as possible&lt;/li&gt;
&lt;li&gt;Include the error messages&lt;/li&gt;
&lt;li&gt;Limit it to the last year or two&lt;/li&gt;
&lt;li&gt;Search within specific sites&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Be as specific as possible
&lt;/h4&gt;

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

&lt;p&gt;You're following a tutorial on a specific technology. Put that at the start of your search. If you're using just JavaScript, start your search with "JavaScript". If you're using React or Vue, start with them. If you're using Next or Nuxt, put them as your first keyword. Be specific.&lt;/p&gt;

&lt;p&gt;One pattern I've seen is to structure your search like this: &lt;code&gt;LANGUAGE/FRAMEWORK VERB KEYWORDS&lt;/code&gt;. This seems to provide better autocomplete suggestions from Google.&lt;/p&gt;

&lt;p&gt;If you're having an issue with a font not loading in a Gatsby site that uses styled-components, search for something like &lt;code&gt;styled-components Gatsby load fonts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you're getting irrelevant results, you can use &lt;code&gt;-&lt;/code&gt; to remove unwanted terms from your search: &lt;code&gt;KEYWORD -UNWANTED_WORD&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, if you're stuck on a Ruby tutorial, include &lt;code&gt;-jewellery&lt;/code&gt;, or &lt;code&gt;-jewelry&lt;/code&gt; if you prefer, in your search to filter out results about the precious stone rather than the programming language.&lt;/p&gt;

&lt;h4&gt;
  
  
  Include the error message
&lt;/h4&gt;

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

&lt;p&gt;If you got an error message and it wasn't enough to tell you what was wrong with your code, it might still prove useful in helping you find a resource that can help you.&lt;/p&gt;

&lt;p&gt;Now, error messages will often include a lot of information that is specific to your application or your machine. Remove this or it might prevent you from finding similar results. Don't copy the entire error message with the stack trace.&lt;/p&gt;

&lt;p&gt;James Roe offerd &lt;a href="https://twitter.com/james_roe/status/948706229785739264" rel="noopener noreferrer"&gt;this advice&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;error code -&amp;gt; error message -&amp;gt; language -&amp;gt; library -&amp;gt; syntax would be my general guide, in descending order of usefulness with other keywords.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I would recommend including the library/framework you are working with. For example, Node.js is used in a lot of build tools and you might get similar looking error messages even though you're using different technologies on top of Node. Search for &lt;code&gt;Nextjs ERROR_MESSAGE&lt;/code&gt; rather than just &lt;code&gt;ERROR_MESSAGE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Say you get this error message from a React app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would search for &lt;code&gt;React Uncaught Invariant Violation: Maximum update depth exceeded.&lt;/code&gt; The rest of the error message and the stack trace is React helping you to debug your code but it's too much detail to make for a good Google search.&lt;/p&gt;

&lt;h4&gt;
  
  
  Limit it to the last year or two
&lt;/h4&gt;

&lt;p&gt;Programming resources go out of date fast and material from a couple of years ago might no longer be helpful to you. Using &lt;code&gt;:before&lt;/code&gt; and &lt;code&gt;:after&lt;/code&gt; in your search will limit the results to before of after a specific date: &lt;code&gt;KEYWORD after:DATE&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I usually limit my searches to the last two years and sometimes just to the last month to check if some recent change to the library of framework may be causing the issue.&lt;/p&gt;

&lt;h4&gt;
  
  
  Search within specific sites
&lt;/h4&gt;

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

&lt;p&gt;You can use Google to search within a specific site even if that site doesn't have a built-in search feature: &lt;code&gt;KEYWORD site:WEBSITE_URL&lt;/code&gt;. This can be handy if you're trying to search through documentation.&lt;/p&gt;

&lt;p&gt;If the tutorial is on a site with comments (such as YouTube, Medium or Dev.to), look there. Several times I've crossed my fingers and scrolled down, hoping someone else had already run into the same issue and gotten an answer.&lt;/p&gt;

&lt;p&gt;If the learning resource you're using has a forum, Slack or Discord, search them. Include the section or video title in your search terms. These will also be great places to ask questions (more below).&lt;/p&gt;

&lt;p&gt;I've found GitHub issues to be particularly useful when I run into problems with libraries and frameworks. If you're experiencing a problem with React, Angular or Vue, someone else likely has too. That said, when you find your exact problem in an open GitHub issue, with no sign of being resolved, it can be a bit demoralizing, so your mileage may vary.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ask
&lt;/h3&gt;

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

&lt;p&gt;Asking for help can be intimidating. You're exposing yourself to the scrutiny of others. Maybe you're worried about wasting someone else's time or worried about looking foolish if the solution turns out to be "obvious" in hindsight. Imposter syndrome can rear its head here.&lt;/p&gt;

&lt;p&gt;If you're intimidated to post a question online, try &lt;a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging" rel="noopener noreferrer"&gt;Rubber Duck Debugging&lt;/a&gt; first. Explain your code line by line out loud to your cat, a desk lamp or the ceiling. Sometimes, explaining a problem can jolt your brain into offering a solution.&lt;/p&gt;

&lt;p&gt;Remember, if you've made a genuine effort to understand a problem before asking for help, you have no reason to feel embarassed or guilty.&lt;/p&gt;

&lt;p&gt;Some sites - I'm thinking of Stack Overflow and Reddit - can be hostile, but there are others that are much friendlier for learners.&lt;/p&gt;

&lt;p&gt;If you're looking for a safe place to ask questions, head to the places where other learners are.&lt;/p&gt;

&lt;p&gt;Learning resources often have a forum - &lt;a href="https://www.freecodecamp.org/" rel="noopener noreferrer"&gt;freeCodeCamp&lt;/a&gt;, &lt;a href="https://teamtreehouse.com/" rel="noopener noreferrer"&gt;Treehouse&lt;/a&gt;, and &lt;a href="https://www.codecademy.com/#" rel="noopener noreferrer"&gt;Codecademy&lt;/a&gt; all do - and I can speak from experience that there are plenty of people there who are happy to help you get unstuck with those courses.&lt;/p&gt;

&lt;p&gt;If you're following a tutorial on YouTube, Dev.to or Medium, post your question in the comments. If the instructor doesn't get back to you, one of the other learners might.&lt;/p&gt;

&lt;p&gt;I have to admit, I'm often reluctant to ask questions online. I don't want to look inept or to annoy anyone. So when I do ask questions, I try to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Include specific details&lt;/li&gt;
&lt;li&gt;Share what you've tried&lt;/li&gt;
&lt;li&gt;Make your code available&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Include specific details
&lt;/h4&gt;

&lt;p&gt;Don't write "My app's not working. Help!". Try something more like "I've gotten to the part of the tutorial where we add the ability to update todos. I can mark a todo as completed in the app interface but when I reload the page it shows it as not completed. I've looked at the React developer tools and the state is updating so I think the problem is that the data's not getting saved to the database. It might be an issue with my updateTodo function. Has anyone else run into this?"&lt;/p&gt;

&lt;p&gt;I try to follow the pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Here's what's meant to be happening.&lt;/li&gt;
&lt;li&gt;Here's what's going wrong.&lt;/li&gt;
&lt;li&gt;Here's what I've tried to fix it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Share what you've tried
&lt;/h4&gt;

&lt;p&gt;Sharing the steps you've tried is important for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It shows that you're not wasting people's time by asking for help without having done any work yourself&lt;/li&gt;
&lt;li&gt;It gives other people an idea of what you've already ruled out&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;People will be much more likely to pitch in and help you if you show that you've given the problem your best and aren't expecting them to solve it for you.&lt;/p&gt;

&lt;p&gt;Sharing your steps will also help them to get up to speed with your code and save them from having to ask you several basic questions.&lt;/p&gt;

&lt;h4&gt;
  
  
  Make your code available
&lt;/h4&gt;

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

&lt;p&gt;It will be much easier for someone to help you if they can see your code for themselves.&lt;/p&gt;

&lt;p&gt;By all means focus on the part of the code where you think the problem is, but also give them a link to the full project so they can read your code in context.&lt;/p&gt;

&lt;p&gt;There are so many services that let you share your code for free. Provide a link to a &lt;a href="https://codepen.io/" rel="noopener noreferrer"&gt;Codepen&lt;/a&gt;, &lt;a href="https://replit.com/" rel="noopener noreferrer"&gt;repl&lt;/a&gt;, &lt;a href="https://codesandbox.io/" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;, or &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; repo so they can view it for themselves.&lt;/p&gt;

&lt;p&gt;If you're having issues with a build on Netlify or Vercel, give them the full error message and stack trace as well as a link to your project.&lt;/p&gt;

&lt;p&gt;It can also be really helpful to include clear screenshots of the problem, whether that's the error message or the weird layout problem you're encountering.&lt;/p&gt;

&lt;p&gt;The more context you can provide, the easier it will be for someone else to understand your code and offer help.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Stuck is Normal, and Can Be Beneficial
&lt;/h3&gt;

&lt;p&gt;Being frustrated is a natural part of programming and of learning any topic. If you never run into an issue, how do you know you're not just copying code without actually learning? It might be more enjoyable to follow a tutorial and have everything work first time, but you will learn the topic much more effectively and thoroughly if you are forced to think about what you are doing. Have a look at the theory of &lt;a href="https://jamesclear.com/beginners-guide-deliberate-practice" rel="noopener noreferrer"&gt;deliberate practice&lt;/a&gt; to find out more about this.&lt;/p&gt;

&lt;p&gt;When you get stuck, it's ok to get frustrated, but don't stay frustrated. Take a break, go for a walk and clear your head.&lt;/p&gt;

&lt;p&gt;When you come back, work the problem. Remember that you have the skills and resources to get yourself unstuck. And remember, too, there are a lot of people who are more than happy to help you if you put the work in first.&lt;/p&gt;

&lt;p&gt;I hope this post was helpful. Best of luck with the next topic you're learning.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Amy Haddad, &lt;a href="https://www.freecodecamp.org/news/how-to-get-unstuck/" rel="noopener noreferrer"&gt;How to Get Unstuck When You Hit a Programming Wall&lt;/a&gt; - freeCodecamp&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ben Awad, &lt;a href="https://www.youtube.com/watch?v=1OX-mns8UJw&amp;amp;t=64s" rel="noopener noreferrer"&gt;How to Google Search Error Messages&lt;/a&gt; - YouTube&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Beth Qiang, &lt;a href="https://www.freecodecamp.org/news/read-search-dont-be-afraid-to-ask-743a23c411b4/" rel="noopener noreferrer"&gt;Read, Search, (Don’t Be Afraid to) Ask&lt;/a&gt; - freeCodeCamp&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bolaji Ayodeji, &lt;a href="https://www.freecodecamp.org/news/asking-effective-questions-a-practical-guide-for-developers/" rel="noopener noreferrer"&gt;How to Ask Effective Questions: A Practical Guide for Developers&lt;/a&gt; - freeCodeCamp&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Colt Steele, &lt;a href="https://www.youtube.com/watch?v=LW9pT246LrI" rel="noopener noreferrer"&gt;The Google History of a High-Paid Sr. Engineer&lt;/a&gt; - YouTube&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Juan Cruz Martinez, &lt;a href="https://betterprogramming.pub/11-tricks-to-master-the-art-of-googling-as-a-software-developer-2e00b7568b7d" rel="noopener noreferrer"&gt;11 Tricks To Master the Art of Googling as a Software Developer&lt;/a&gt; - BetterProgramming&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Swyx, &lt;a href="https://dev.to/swyx/how-to-google-your-errors-2l6o"&gt;How To Google Your Errors&lt;/a&gt; - Dev.to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>debugging</category>
      <category>learning</category>
      <category>stuck</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Connect a Node App to MongoDB Atlas</title>
      <dc:creator>Gerard Hynes</dc:creator>
      <pubDate>Thu, 29 Jul 2021 15:02:52 +0000</pubDate>
      <link>https://forem.com/ger_hynes/how-to-connect-a-node-app-to-mongodb-atlas-43ek</link>
      <guid>https://forem.com/ger_hynes/how-to-connect-a-node-app-to-mongodb-atlas-43ek</guid>
      <description>&lt;p&gt;MongoDB is a popular NoSQL database choice for Node apps. There's a reason that the acronyms MERN stack, MEAN stack and even MEVN stack exist to describe an app built on MongoDB, Express, a JavaScript framework (whether React, Angular or Vue), and Node.&lt;/p&gt;

&lt;p&gt;If you're learning how to work with MongoDB and Node, setting up a database on your own computer can be a little bit of a headache. Thankfully, MongoDB offer a cloud-based database platform, &lt;a href="https://www.mongodb.com/cloud/atlas" rel="noopener noreferrer"&gt;MongoDB Atlas&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I recently built a few projects with Node and MongoDB Atlas and felt it might be useful to write up a quick guide to how to get the two to talk to each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Set up your MongoDB Atlas Account and Cluster
&lt;/h3&gt;

&lt;p&gt;First things first, go to the &lt;a href="https://www.mongodb.com/cloud/atlas" rel="noopener noreferrer"&gt;MongoDB Atlas website&lt;/a&gt; and create a free account. You can choose whatever name you want for your organization and project. Choose JavaScript as your preferred language.&lt;/p&gt;

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

&lt;p&gt;Next choose a free shared cluster. This will be enough for demos and small personal projects.&lt;/p&gt;

&lt;p&gt;When you're invited to create a starter cluster, you can leave the Cloud Provider and Region as the defaults (unless you have strong feelings about them) and click &lt;strong&gt;Create Cluster&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;You'll now be brought to your admin dashboard. Click on &lt;strong&gt;Create a New Cluster&lt;/strong&gt;. This can take a couple of minutes.&lt;/p&gt;

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

&lt;p&gt;Once your cluster is ready, click on the &lt;strong&gt;Connect&lt;/strong&gt; button in the sandbox.&lt;/p&gt;

&lt;p&gt;Allow access from all IP addresses. This would be a terrible idea in production but this is just a demo for learning purposes.&lt;/p&gt;

&lt;p&gt;Next, create a new user for the database and choose a password. Store these somewhere safe, like your password manager.&lt;/p&gt;

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

&lt;p&gt;Now click on &lt;strong&gt;Choose a connection method&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Connect your application&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Under &lt;strong&gt;Add your connection string into your application code&lt;/strong&gt; you'll see a URI with the format &lt;code&gt;mongodb+srv://&amp;lt;username&amp;gt;:&amp;lt;password&amp;gt;@&amp;lt;cluster-name&amp;gt;.mongodb.net/&amp;lt;db-name&amp;gt;?retryWrites=true&amp;amp;w=majority&lt;/code&gt;. The username, cluster-name and db-name fields will be automatically filled out.&lt;/p&gt;

&lt;p&gt;Copy this URI to your clipboard. You'll need it in a minute.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Step 2 - Make a Node App if you don't already have one
&lt;/h3&gt;

&lt;p&gt;If you don't have a Node app to hand, you can &lt;a href="https://github.com/gerhynes/node-mongodb-atlas/tree/starter-code" rel="noopener noreferrer"&gt;download the starter code for a very basic Express app from this repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;npm install&lt;/code&gt; to install Express, the only dependency.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;app.js&lt;/code&gt; file should look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Your app is listening on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your command line, run &lt;code&gt;node app.js&lt;/code&gt; and you should see the confirmation message that your app is listening on a particular port.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Store Environmental Variables
&lt;/h3&gt;

&lt;p&gt;Remember your MongoDB Atlas URI? You don't want to just paste that into your code where it could get committed to Git and potentially publicly exposed.&lt;/p&gt;

&lt;p&gt;Instead, we're going to save it as an environmental variable.&lt;/p&gt;

&lt;p&gt;Install the &lt;a href="https://www.npmjs.com/package/dotenv" rel="noopener noreferrer"&gt;dotenv package&lt;/a&gt; with &lt;code&gt;npm install dotenv&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in the root of your project, paste in your URI, and assign it to a &lt;code&gt;DB_URI&lt;/code&gt; variable. Make sure your version includes your password as well as your username, cluster name and database name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// .env&lt;/span&gt;
&lt;span class="nx"&gt;DB_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;mongodb&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;srv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//&amp;lt;username&amp;gt;:&amp;lt;password&amp;gt;@&amp;lt;cluster-name&amp;gt;.mongodb.net/&amp;lt;db-name&amp;gt;?retryWrites=true&amp;amp;w=majority&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4 - Configure your Database Connection
&lt;/h3&gt;

&lt;p&gt;To keep things organized, I keep my database config in its own file.&lt;/p&gt;

&lt;p&gt;In the root of your project, create a &lt;code&gt;db.js&lt;/code&gt; file. This will contain all the configuration for connecting to your database.&lt;/p&gt;

&lt;p&gt;We're going to use &lt;a href="https://mongoosejs.com/" rel="noopener noreferrer"&gt;Mongoose&lt;/a&gt; to handle connecting to our database.&lt;/p&gt;

&lt;p&gt;Install Mongoose with &lt;code&gt;npm install mongoose&lt;/code&gt; and import it into &lt;code&gt;db.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Import your database URI as &lt;code&gt;db&lt;/code&gt; from &lt;code&gt;process.env.DB_URI&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;connectDB&lt;/code&gt; function. Make sure you mark it as an &lt;code&gt;async&lt;/code&gt; function as it will take some amount of time to connect to your database.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;connectDB&lt;/code&gt;, create a &lt;code&gt;try-catch&lt;/code&gt; block to handle any errors that occur.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;try&lt;/code&gt; block, await &lt;code&gt;mongoose.connect()&lt;/code&gt;. Pass it the &lt;code&gt;db&lt;/code&gt; variable and a settings object. In the settings object, set &lt;code&gt;useNewUrlParser&lt;/code&gt; and &lt;code&gt;useUnifiedTopology&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;. This will prevent Mongoose from giving you warnings. Mongoose explains the warnings in their &lt;a href="https://mongoosejs.com/docs/deprecations.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's also a good habit to &lt;code&gt;console.log&lt;/code&gt; a success message to tell you you've connected to your database. I once spent an hour trying to debug a database connection simply because I wasn't telling myself it was connected.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;catch&lt;/code&gt; block, &lt;code&gt;console.error&lt;/code&gt; any error you receive and use &lt;code&gt;process.exit(1)&lt;/code&gt; to terminate the process if an error occurs.&lt;/p&gt;

&lt;p&gt;Finally, export the &lt;code&gt;connectDB&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;db.js&lt;/code&gt; file should now look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// db.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_URI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;connectDB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;useNewUrlParser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;useUnifiedTopology&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MongoDB connected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;connectDB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5 - Time to Connect to Your Database
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;app.js&lt;/code&gt; file, require &lt;code&gt;dotenv&lt;/code&gt; and call the &lt;code&gt;config&lt;/code&gt; method on it.&lt;/p&gt;

&lt;p&gt;Import the &lt;code&gt;connectDB&lt;/code&gt; function and call it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.js&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connectDB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Connect to database&lt;/span&gt;
&lt;span class="nf"&gt;connectDB&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Your app is listening on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations, your Node app is now connected to your MongoDB Atlas cluster. If you run &lt;code&gt;node app.js&lt;/code&gt;, you'll see two messages printed to your console: that your app is running and that you've connected to your database. From here you can start to write schemas and perform CRUD operations with your data.&lt;/p&gt;

&lt;p&gt;If you ran into any issues, &lt;a href="https://github.com/gerhynes/node-mongodb-atlas" rel="noopener noreferrer"&gt;the code for this demo app&lt;/a&gt; is in this repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.atlas.mongodb.com/" rel="noopener noreferrer"&gt;MongoDB Atlas Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MongoDB, &lt;a href="https://youtu.be/rPqRyYJmx2g" rel="noopener noreferrer"&gt;Getting Your Free MongoDB Atlas Cluster&lt;/a&gt; - YouTube&lt;/li&gt;
&lt;li&gt;MongoDB, &lt;a href="https://www.freecodecamp.org/news/get-started-with-mongodb-atlas/" rel="noopener noreferrer"&gt;MongoDB Atlas Tutorial – How to Get Started&lt;/a&gt; - freeCodeCamp&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>node</category>
      <category>mongodb</category>
      <category>database</category>
    </item>
    <item>
      <title>Turning a Personal Site into a Portfolio</title>
      <dc:creator>Gerard Hynes</dc:creator>
      <pubDate>Thu, 29 Jul 2021 14:48:53 +0000</pubDate>
      <link>https://forem.com/ger_hynes/turning-a-personal-site-into-a-portfolio-2484</link>
      <guid>https://forem.com/ger_hynes/turning-a-personal-site-into-a-portfolio-2484</guid>
      <description>&lt;p&gt;Personal websites are often neglected. In my case, &lt;a href="https://gerhynes.github.io/portfolio"&gt;my old site&lt;/a&gt; hadn't had a redesign in 2 years 😬. Since then I've built dozens of small projects and learned a number of new technologies. But my site didn't reflect any of that.&lt;/p&gt;

&lt;h3&gt;
  
  
  The old site and its problems
&lt;/h3&gt;

&lt;p&gt;The old site was a pretty accurate snapshot of my technical abilities at the time. It was a purely static site, with just a little bit of JavaScript for interactions and Sass for styling. I was in the middle of learning CSS Grid and about to start a long period of getting better at JavaScript. I hadn't even touched a frontend framework like React.&lt;/p&gt;

&lt;p&gt;The main problem was that the site didn't have a clear message. The old landing page said "I'm a self-taught web developer and programmer". That's fine, but it's pretty generic, and doesn't really tell the visitor what I do or where my interests lie.&lt;/p&gt;

&lt;p&gt;The site also failed the "show, don't tell" rule of writing. I did what everyone else seemed to be doing and listed the technologies I had experience with and linked to some projects. But I failed at properly demonstrating those skills or explaining why these projects mattered, how I had built them, or what I had learned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8LhAIpqr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2rxd8bqmapbiih0ifwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8LhAIpqr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2rxd8bqmapbiih0ifwy.png" alt="Screenshot of skills section from old site"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing these problems
&lt;/h3&gt;

&lt;p&gt;After thinking about it, I decided that a portfolio site should quickly convey three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your personality&lt;/li&gt;
&lt;li&gt;Your professional interests&lt;/li&gt;
&lt;li&gt;Your technical skills&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the last year I've fallen down the JavaScript rabbit hole and gotten really interested in the &lt;a href="https://jamstack.org/"&gt;Jamstack&lt;/a&gt; as an architecture for building sites and web apps. My &lt;a href="https://gerardhynes.com"&gt;new landing page&lt;/a&gt; reflects this: "I make fast, modern sites and apps using the Jamstack and fullstack JavaScript".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kAL2Xp0d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnkqa3r9swm0gfmgy6c0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kAL2Xp0d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnkqa3r9swm0gfmgy6c0.png" alt="Old and new site side by side"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I rebuilt the site I intended for it to better demonstrate my current interests and technical skills, so clearly it should have a much greater focus on JavaScript. I settled on a Jamstack site built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.gatsbyjs.com/"&gt;Gatsby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mdxjs.com/"&gt;MDX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://styled-components.com/"&gt;styled-components&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gatsby helps make the site fast by default, with built-in code splitting and image optimization. Markdown provides a pretty pleasant writing experience (at least for me), and MDX gives me the option to embed React components if I ever want to include videos, graphs or Codepens. styled-components offer many of the benefits of Sass, such as code organization, nesting and variables, with the added advantage that the CSS is scoped to individual components.&lt;/p&gt;

&lt;p&gt;Sure, this might be overkill for a personal website, but I took comfort from Colby Fayock's post, when he says &lt;a href="https://www.colbyfayock.com/2020/07/youre-allowed-to-overengineer-your-blog/"&gt;You're Allowed to Overengineer Your Blog&lt;/a&gt;, especially in order to solidify the technologies you're learning.&lt;/p&gt;

&lt;p&gt;I've also made a concerted effort to update my personal projects from basic detail cards into proper case studies. Here I followed Josh W Comeau's &lt;a href="https://joshwcomeau.com/effective-portfolio/"&gt;advice on making a more effective portfolio&lt;/a&gt;, by fleshing out the project's goals, tech stack, any pain points encountered, and the lessons learned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jA81ZYn2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4d7dxhp6wskrdp9o1fu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jA81ZYn2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4d7dxhp6wskrdp9o1fu.png" alt="Screenshots of old and new project descriptions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, in an attempt to write more, I added a writing section. If you've read Barbara Oakley's &lt;a href="https://barbaraoakley.com/books/a-mind-for-numbers/"&gt;A Mind for Numbers&lt;/a&gt; or taken her excellent course on &lt;a href="https://www.coursera.org/learn/learning-how-to-learn"&gt;Learning how to Learn&lt;/a&gt;, you'll know that trying to explain concepts clearly in writing is a really effective way to check if you actually understand them and also make those concepts stick. Some of these posts might even prove useful for other people.&lt;/p&gt;

&lt;p&gt;I've heard that if a podcast can make it past 7 episodes, it'll probably survive. Let's see if I can write more than 7 posts here.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>jamstack</category>
      <category>portfolio</category>
    </item>
  </channel>
</rss>
