<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matt Wing</title>
    <description>The latest articles on DEV Community by Matt Wing (@wingmatt).</description>
    <link>https://dev.to/wingmatt</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%2F263111%2F1624a002-9e1f-4827-ba2f-ace6cfd7d11c.png</url>
      <title>DEV Community: Matt Wing</title>
      <link>https://dev.to/wingmatt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wingmatt"/>
    <language>en</language>
    <item>
      <title>📅 The Most Efficient Self-Taught Learning is Routine</title>
      <dc:creator>Matt Wing</dc:creator>
      <pubDate>Tue, 26 Apr 2022 03:27:58 +0000</pubDate>
      <link>https://dev.to/wingmatt/the-most-efficient-self-taught-learning-is-routine-45j3</link>
      <guid>https://dev.to/wingmatt/the-most-efficient-self-taught-learning-is-routine-45j3</guid>
      <description>&lt;p&gt;I love to learn, but I hate finding time for it.&lt;/p&gt;

&lt;p&gt;We all only have 24 hours in a day. Between work, sleep, and everything else, you're probably juggling a lot already! The challenge for anyone doing self-taught learning is finding out how much time you can set aside &lt;strong&gt;consistently&lt;/strong&gt; — fitting it into your regular routine, the cadence of your daily life.&lt;/p&gt;

&lt;p&gt;Taking two hours to dive into something every other Saturday is a great supplement to your regular cadence. But if that's all you can do, you're gonna spend a good chunk of each time block just trying to remember where you left off.&lt;/p&gt;

&lt;p&gt;If you can set aside even a half hour every weekday, or even just three days a week, you will feel the progress. And any big blocks of time you &lt;em&gt;can&lt;/em&gt; snag will be infinitely more productive!&lt;/p&gt;

&lt;p&gt;Fair warning that, best case, you'll be taking this time from your solo free time. Yes, that still sucks. But it's still better than depriving yourself of sleep, or neglecting your relationships.&lt;/p&gt;

&lt;p&gt;It's common for people trying to learn new skills to be drained by the time they get time for it. I found a way around this in my schedule by doing it first thing in the morning, before I hop into any other work. This works for me because I'm already awake a couple hours before my job typically starts.&lt;/p&gt;

&lt;p&gt;Everyone's schedule is different. As long as you're making the time and protecting it wherever it lands on your schedule, you're moving forward along your path. It doesn't have to be a huge long session each time, and it doesn't even have to be every day. It just needs to be &lt;strong&gt;consistent&lt;/strong&gt;!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>🔍 Parsing Schema Data with node-html-parser</title>
      <dc:creator>Matt Wing</dc:creator>
      <pubDate>Wed, 29 Sep 2021 15:29:23 +0000</pubDate>
      <link>https://dev.to/wingmatt/parsing-schema-data-with-node-html-parser-20ad</link>
      <guid>https://dev.to/wingmatt/parsing-schema-data-with-node-html-parser-20ad</guid>
      <description>&lt;p&gt;Did you know that there's a whole JSON object schema for providing machine-readable information about the contents of your website? Google uses the data in these objects to fill out search results and build rich snippets.&lt;/p&gt;

&lt;p&gt;Here's a secret - it can power other stuff too. For example, I'm building a Node JS web app that includes the ability to plug a URL in and get a list of that recipe's ingredients.&lt;/p&gt;

&lt;p&gt;Want to start parsing data yourself? Read on!&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fetching the raw HTML&lt;/li&gt;
&lt;li&gt;Making the Raw HTML Parse-able&lt;/li&gt;
&lt;li&gt;Finding the right Schema object out of all of the ones on the page&lt;/li&gt;
&lt;li&gt;Grabbing the right data out of that schema object&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fetching the raw HTML
&lt;/h2&gt;

&lt;p&gt;First things first — we want to be able to fetch the HTML code of whatever link we end up pasting into our app. &lt;/p&gt;

&lt;p&gt;There are a lot of ways to do this in Node JS. For this tutorial, we'll be using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch"&gt;native JavaScript &lt;code&gt;fetch&lt;/code&gt; API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With that in mind, here's how to make &lt;code&gt;fetch&lt;/code&gt; happen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Use an async function so we can wait for the fetch to complete&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getHtmlStringFromUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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="c1"&gt;// responseHtml is a huge string containing the entire web page HTML.&lt;/span&gt;
      &lt;span class="c1"&gt;// In the next section, we'll process it into something we can work with&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;h2&gt;
  
  
  Making the Raw HTML Parse-able
&lt;/h2&gt;

&lt;p&gt;When we first fetch a URL and grab the response body, it's one enormous text string. There's HTML in there, but we can't really work with it yet. We need to plug this string into an HTML parser that will let us use DOM selectors to pick out the useful bits.&lt;/p&gt;

&lt;p&gt;node-html-parser is my personal choice for this. It lets us use all the usual JavaScript DOM selector methods, and it's pretty fast too. Add it to your project with this terminal command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add node-html-parser&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then import the parse command from the package into the JS file where you'll be using it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { parse } from "node-html-parser";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we can take the response body string, plug it into our parser, and get to the real fun:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-html-parser&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;getHtmlDocumentFromUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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="c1"&gt;// parse the HTML string into a DOM-like object we can navigate&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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;That's all we need to get the HTML into something we can sift through! The returned object has all the same methods as a typical document object, such as querySelector, getElementByID, and so on. &lt;/p&gt;

&lt;p&gt;So, how do we work it to find the structured data we're looking for?&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the right Schema object(s)
&lt;/h2&gt;

&lt;p&gt;The nice thing about working with structured data is that you can make some assumptions about the data you're processing, because it &lt;em&gt;has&lt;/em&gt; to be structured in a way that web crawlers can understand to be useful.&lt;/p&gt;

&lt;p&gt;The structured data Schema objects we're looking for are going to be found within &lt;code&gt;ld+json&lt;/code&gt; script tags. Now that we've DOMified the HTML, we can run queries on it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-html-parser&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;getSchemaNodeListFromUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// Create a NodeList of elements containing the page's structured data JSON. So close to useful!&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;structuredData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script[type="application/ld+json"]&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;That will give us a NodeList of all the matching elements. That's close to perfect, but it's not a true array and could give us errors if we try to treat it like one (which we will soon). So let's turn it into an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-html-parser&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;getSchemaArrayFromUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// Create an ARRAY of elements containing the page's structured data JSON. Just one more step!&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;structuredData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script[type="application/ld+json"]&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;Now we have an array of structured data nodes. In a way, we're back to square one with data that is &lt;em&gt;so close&lt;/em&gt; to being useful. To make it useful, we need to grab the innerHTML of each node, which will come out as a big string. Then we can parse that into ✨real JSON!✨&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-html-parser&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;getJsonFromUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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;structuredData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script[type="application/ld+json"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="c1"&gt;// Get an array containing the contents of each structured data element on the page. This is the ✨useful stuff✨&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;structuredDataJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;structuredData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="c1"&gt;// We also flatten the array with .flat() to handle how some sites structure their schema data. See epilogue for more info&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;Whoa, look at us. We've got the real, actual JSON object now. If you log structuredDataJson to your console, you'll see an array of structured data objects! Huzzah 🎉 &lt;/p&gt;

&lt;p&gt;But of course, we're not done yet! There is likely to be a ton of data you don't need in this array, in addition to whatever you're actually looking for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Grabbing the right data out of that schema object
&lt;/h2&gt;

&lt;p&gt;You're looking for some sort of specific data out of these objects. In my case, I'm looking for the list of &lt;a href="https://schema.org/recipeIngredient"&gt;ingredients&lt;/a&gt; within the &lt;a href="https://schema.org/Recipe"&gt;Recipe object&lt;/a&gt;. So, now that we have actual JSON, we can view certain properties and use it to whittle our array down to a single, useful, piece of data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-html-parser&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;getIngredientsFromUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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;structuredData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script[type="application/ld+json"]&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;structuredDataJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;structuredData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="c1"&gt;// Look for a Recipe schema and return its ingredients if it exists     &lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recipeData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;structuredDataJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Recipe&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;recipeData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;recipeData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recipeIngredient&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;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;If one of the structured data objects is for a Recipe, we'll get the array of ingredients we're looking for. If not, the function will return &lt;code&gt;null&lt;/code&gt; so we know it failed to find what we were looking for. &lt;/p&gt;

&lt;p&gt;That's it! We've parsed the HTML into JSON into the actual thing we need 🎉&lt;/p&gt;

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

&lt;p&gt;At this point, you have a function that takes a URL and returns an array of whatever information you're looking for. This general process can be used to do a whole lot of interesting stuff depending on what you're grabbing. &lt;a href="https://codesandbox.io/s/nextjs-recipe-schema-data-parsing-example-tblx7"&gt;Here's an example I put together to grab the ingredients within a recipe page.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://schema.org/docs/schemas.html"&gt;Here are some of the most common schemas out there&lt;/a&gt; for inspiration. In my case, I'm parsing recipe ingredients so I can see if they're in my pantry, and add them to my shopping list if they're not. &lt;/p&gt;

&lt;p&gt;How about you? If you end up using this process to parse website data in your web app, let me know what you're doing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Epilogue: Handling Edge Cases with the flat() method
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, structured data has to be readable by web crawlers to be useful, so we can make some assumptions about what it will look like. Still, we're ultimately trusting people to build their websites according to a certain convention, so you still might run into some issues across different websites and pages.&lt;/p&gt;

&lt;p&gt;When I was testing my recipe parser, I ran into a few websites that structured their data in non-standard ways, which caused some trouble early on. The most common issue I found was that some sites would wrap their schema JSON within an array. This prevented my array.find() method from finding any of the data within the nested array.&lt;/p&gt;

&lt;p&gt;In my production code, I handle this by flattening the parsed JSON to remove any nested arrays before I start looking for specific data. Here's what that looks like with the example code we've been using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-html-parser&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;getHtmlFromUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseHtml&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;structuredData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script[type="application/ld+json"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="c1"&gt;// Adding .flat() to the line below handles the most common edge cases I've found so far! &lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;structuredDataJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;structuredData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;flat&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;recipeData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;structuredDataJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Recipe&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;recipeData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;recipeData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recipeIngredient&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;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;



</description>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Managing Side Projects to Account for Life</title>
      <dc:creator>Matt Wing</dc:creator>
      <pubDate>Thu, 12 Mar 2020 05:25:15 +0000</pubDate>
      <link>https://dev.to/wingmatt/managing-side-projects-to-account-for-life-12dj</link>
      <guid>https://dev.to/wingmatt/managing-side-projects-to-account-for-life-12dj</guid>
      <description>&lt;p&gt;Everyone loves a good side project! It's your chance to actually work with the shiny new technology you've read 12 tutorials about, to add some real code to your resume to show your proficiency with the shiniest new technologies, and re-learn just how difficult it can be to step outside your coding comfort zone.&lt;/p&gt;

&lt;p&gt;It's common for coders to have a big barrel full of abandoned side projects. Each one is a milestone in a way. I personally have some concepts I've started from scratch on 3 or 4 times.&lt;/p&gt;

&lt;p&gt;Much like the first few levels in World of Warcraft, the first few hours of a new project are full of excitement. Anything involving a package manager gives you those first moments where you watch things fly by in the console and feel like a master hacker as you sip on your beverage of choice. Then you plug in the example code and see it work like it did in the example! Just like that! Wow!&lt;/p&gt;

&lt;p&gt;Eventually the joy ride ends as you come to terms with the vast gulf that spans between where your project is now, and its completed state. Invoking the magic words "mimimum viable product" can only do so much to reduce the scope of your dream when you're hoping to do something amazing. The rational part of your brain knows that spending an hour a day on this will get you to the finish line eventually. &lt;/p&gt;

&lt;p&gt;That would be all we need for motivation if humans ran entirely on rational thought! Alas, most side projects do eventually fizzle out as we tire of using our spare time to bang our head against the wall in frustration. Even with a mild concussion, the dream that sparked the side project's creation never dies.&lt;/p&gt;

&lt;p&gt;When you're ready to dive back into things, it's easy to feel overwhelmed by re-acquainting yourself with your old code. It's like loading up a game you almost beat six months ago and trying to remember what you were supposed to be doing. &lt;/p&gt;

&lt;p&gt;How do we make the most of our fizzled-out projects to make the most of these bursts of renewed motivation? Here are a few suggestions from someone who has plenty of stalled projects to experiment with:&lt;/p&gt;

&lt;h2&gt;
  
  
  Document the heck out of them
&lt;/h2&gt;

&lt;p&gt;Write up rough design documents. Map out what classes or functions you think you'll need to make things happen. You could even write tests for them that roughly describe how you expect them to work. These don't need to be detailed or fancy - they're just for you.&lt;/p&gt;

&lt;p&gt;This does a few things for you: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just like in "real" software projects, you'll be able to reconsider architecture and design decisions before you're halfway through implementing your first guess at how things should be. It's so much easier to draw a new diagram than it is to refactor your app from the ground up.&lt;/li&gt;
&lt;li&gt;If (when?) your motivation for working on the project dries up, you can take a break and easily jump back in when you're ready. If you kept track of your progress too, you can just jump back in from where you left off.&lt;/li&gt;
&lt;li&gt;If you want to start from scratch, your planning docs won't be tightly tied to specific code, so you can use a fancy new framework instead of the &lt;em&gt;old&lt;/em&gt; framework you were excited about the last time you started things up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I just did this in the aftermath of my most recent project hiatus. I wrote out a rough outline of the type of data the most complex objects would need to hold onto, some pseudocode for the most complicated functions, and a few basic unit tests. I found that it's easier for me to come up with unit testing ideas on paper than in the IDE - maybe because I don't get hung up on getting the syntax perfect as I'm trying to come up with them. What will you find easier to plan on paper? Only one way to find out!&lt;/p&gt;

&lt;h2&gt;
  
  
  Use what you've learned for next time
&lt;/h2&gt;

&lt;p&gt;So... you didn't write up any design documents. That's okay! You moved fast, broke things, and got out of there. We've all done the same. Chances are good that you got stuck on a hard problem. In web development, running into one of those usually means one of three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The real problem is that you don't fully understand what's going on, which makes a small problem seem like a huge problem.&lt;/li&gt;
&lt;li&gt;You're going to learn that someone solved that problem for you in a library - thanks, open source software!&lt;/li&gt;
&lt;li&gt;You are a pioneer staking your claim on something that, truly, no one has done before. If you solve this, you can become the hero in the last scenario.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two situations are pretty common, at least in my experience. I've come back to projects before and found that the biggest problems had melted away.&lt;/p&gt;

&lt;p&gt;The third scenario is why people say things like "the things worth doing in life are hard." If you run into a truly unique problem and keep puttering away at it, you'll become a master of that problem's domain before you know it.&lt;/p&gt;

&lt;p&gt;No matter what stopped you in your tracks, your experience taught you something that no tutorial was going to show you. Maybe you learned the limits of the shiny new technology that looked so effortless in the demos. Maybe you found the edges of a library's helpfulness, or a bug you can report. No matter what happened, you learned something from it, so the next time you start a side project, you'll be that much more knowledgeable about how to make it work.&lt;/p&gt;

&lt;p&gt;Like I said before, these are the practices I'm working on for myself in order to make the most of my personal programming time. What do you do to improve your chances of taking a side project to the finish line?&lt;/p&gt;

</description>
      <category>personal</category>
      <category>project</category>
      <category>planning</category>
    </item>
  </channel>
</rss>
