<?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: Eric McCormick</title>
    <description>The latest articles on DEV Community by Eric McCormick (@edm00se).</description>
    <link>https://dev.to/edm00se</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%2F1378%2F25a0cece-3fbd-48be-845c-d8eb8f83301b.jpg</url>
      <title>DEV Community: Eric McCormick</title>
      <link>https://dev.to/edm00se</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/edm00se"/>
    <language>en</language>
    <item>
      <title>Putting The Bots To Work</title>
      <dc:creator>Eric McCormick</dc:creator>
      <pubDate>Fri, 10 Nov 2023 21:58:45 +0000</pubDate>
      <link>https://dev.to/edm00se/putting-the-bots-to-work-45lo</link>
      <guid>https://dev.to/edm00se/putting-the-bots-to-work-45lo</guid>
      <description>&lt;p&gt;Happy November everybody! I made it through October and in spite of some of the doom and gloom to come in this one, I still had &lt;em&gt;some&lt;/em&gt; fun in moderating my usual contributing open source repository to Hacktoberfest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hacktoberfest 2023 and Lessons Learned
&lt;/h3&gt;

&lt;p&gt;Since 2018, I've been not only participating, but opening up an open source repository of mine for contributions with &lt;a href="https://hacktoberfest.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt;. This was Hacktoberfest's 10th year and I've contributed for most of them, but the desire to contribute a repository was born from a desire to share something fun and help others gain in the ways of open source contribution. This year didn't go perfectly, they never do, and I had to learn a few things, which I usually do. Primarily of note this year was that the amount of traffic my humble repo got was significantly larger than any previous year. How much more? One eager individual submitted 17 PRs immediately and all together, which is more than I had a couple of years. Here's some data charted out for those that like such things. There's also a curious uptick in this year's number of un-merged PRs marked in the chart as "gap", some were duplicates that could have been easily found (a requirement in the checks specified in my repo's Pull Request template btw), others were low effort and not the sort of contributions requested, and some were even abandoned as soon as there was any feedback.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bNBl9y6F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://edm00se.io/assets/static/pr_data_and_graph_updated.30a8f75.4d2ce3563ae15c0f4944a8f7fbcc7a68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bNBl9y6F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://edm00se.io/assets/static/pr_data_and_graph_updated.30a8f75.4d2ce3563ae15c0f4944a8f7fbcc7a68.png" alt="spreadsheet screenshot of by year values of opened vs merged PRs and expressed as a bar chart" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're looking to get some Pull Request data, my search filter to limit by creation within a given month of a year and remove dependabot looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;is:pr created:2023-10-01..2023-10-31
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To filter out dependabot, which showed up under two names in my repo, add &lt;code&gt;-author:app/dependabot -author:app/dependabot-preview&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to see merged, tack on &lt;code&gt;state:merged&lt;/code&gt; to that query. &lt;a href="https://github.com/edm00se/awesome-board-games/pulls?q=is%3Apr+created%3A2018-10-01..2018-10-31+-author%3Aapp%2Fdependabot+-author%3Aapp%2Fdependabot-preview+state%3Amerged+" rel="noopener noreferrer"&gt;Here's the merged search for this October for reference&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  When Do The Bots Come In?
&lt;/h3&gt;

&lt;p&gt;A little over a week into October, I had realized I had a problem. I knew I had to do something as nearly a hundred PRs had been opened within the first two weeks. So I did what any seasoned developer would do, I looked for a "cheat" to speed up my efforts. Enter the bots. I decided to see what responses I would get from some of the LLM chat "AI" interfaces in an attempt to compare them and see how close to a working output I could get without needing to do the work myself; the adage of "a good developer is a lazy developer" comes to mind.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Showdown
&lt;/h3&gt;

&lt;p&gt;I began by asking for a &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Action&lt;/a&gt; that would suit my needs, specifically one to detect other open PRs by the author and fail the check should it be over a specified threshold. I then asked for the bot to update should I apply the "hacktoberfest-accepted" label, allowing me as the maintainer to effectively override this, since I did expect a few log jams that could need clearing. I repeated this two part request for each of those I tried out. I also only tested those I could use for free, because this was a one-off and I'm a bit of a cheap skate with disposable technology.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;a href="https://chat.openai.com" rel="noopener noreferrer"&gt;OpenAI ChatGPT&lt;/a&gt; (3.5, aka the free one)
&lt;/h4&gt;

&lt;p&gt;I began with the one that is frequently talked about most. I was a bit surprised by this one as it had my highest expectations, in spite of low expectations in general. On the first ask, I was given a mild surprise as I was returned code in two parts, not one. The first was a node script using &lt;code&gt;@actions/core&lt;/code&gt; and &lt;code&gt;@actions/github&lt;/code&gt; to do the heavy lifting. It reads about how you would expect.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The wiring up of the GitHub Action via its workflow YAML was also quite straight forward. It checks out the code, installs the node dependencies, then executes the script.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;After my follow up to allow for the label to override the failing check when present.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  The Other Thing
&lt;/h5&gt;

&lt;p&gt;The Eagle eyed among you may have noticed something which dates the response and the built LLM a bit. While everything seemed functional, the node version specified was node 14. Node 14 was in active LTS for a while, then moved to maintenance for security updates, and then was End Of Life'd in April of this year (2023) in accordance with the &lt;a href="https://nodejs.org/en/about/previous-releases" rel="noopener noreferrer"&gt;node release schedule&lt;/a&gt;. I asked for it to be updated to latest LTS and was basically told to figure it out myself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xtVHSEFZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://edm00se.io/assets/static/ChatGPT_dated_node_version_knowledge.b87efdc.1ac8cba9f41f66ca2174e3fc4819df5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xtVHSEFZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://edm00se.io/assets/static/ChatGPT_dated_node_version_knowledge.b87efdc.1ac8cba9f41f66ca2174e3fc4819df5a.png" alt="a reply from ChatGPT telling me to just figure it out myself" width="674" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I know many like to joke about the volatility and pace of web development compared to other development circles, but I found it a little remarkable that ChatGPT couldn't just do a basic query to at least tell me what to update to for the latest LTS. It's not that I needed it, but that it would be incredibly simple and highlights the limits of LLMs being trained as they were when that one was built.&lt;/p&gt;

&lt;h5&gt;
  
  
  Verdict
&lt;/h5&gt;

&lt;p&gt;This wasn't a bad place to start, but I decided to try the others once this split the files into two. This combined with the dated knowledge of node made me wonder if that was what I should persue as I was really looking for a drop-in solution that required no other files.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://bard.google.com" rel="noopener noreferrer"&gt;Google Bard&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Bard started strong, rolling up all the work into a single step and making good use of the &lt;code&gt;actions/github-script&lt;/code&gt; to both attain the needed dependency functionality and also keep it inside the one file. Note: in no cases did I specify the desire for a single file, but nearly all returned with a single file. Here's what it returned after my update to request the label to escape the condition.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;A nice feature I noticed only for Bard was the citation of sources. That's right, they call it out with a numbered marker on the side, clicking on it gives the hyperlink, as does it show in the footer of the response. This was an immensely useful feature and it didn't matter that the cited link was in Japanese, using Google Translate I was then able to read and understand the majority of the source. That the source was cited and that it was done with specificity as to what component it was generating gave me some level of assurance either to vet the information myself or at least know who to blame 🙃.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w7NYAjdR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://edm00se.io/assets/static/bard_citing_source.1aec693.175e1906794aa5e3514d7cc80074515c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w7NYAjdR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://edm00se.io/assets/static/bard_citing_source.1aec693.175e1906794aa5e3514d7cc80074515c.png" alt="Bard cites specific sources under some circumstances, footer note with hyperlink shown" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Verdict
&lt;/h5&gt;

&lt;p&gt;This looked promising, so promising that I attempted to implement the action, in a test repository at first. Until it was deployed in my actual repository with other people submitting PRs I didn't realize that I was apparently the noted "author" and had to make more changes. So this one was my starting point, but it was no out of the box working experience. That said, knowing the source it used to help come up with the answer was good, in that I could read up on what the human being that it pulled from was talking about.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://claude.ai" rel="noopener noreferrer"&gt;Claude&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;For any who aren't aware of it, Claude is made &lt;a href="https://www.anthropic.com/index/introducing-claude" rel="noopener noreferrer"&gt;by Anthropic and at least claims&lt;/a&gt; to train its models to be "helpful, honest, and harmless". What that functionally means, I'm not entirely certain of, but with any luck it means they aren't stealing some &lt;a href="https://theoatmeal.com/comics/exposure" rel="noopener noreferrer"&gt;poor artist's exposure bucks&lt;/a&gt;. On first request, it gave me something that wouldn't work, then on calling it out it gave me back the exact same script, except that it had capitalized the word "count". Maybe this sort of question isn't the sort Claude is good for as I've had a couple decent interactions with other tests I've run. See if you can spot the issue.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Right out the gate, wherever Claude pulled this from was attempting to execute the action only on &lt;code&gt;workflow_dispatch&lt;/code&gt;, which being familiar with GitHub Actions I can tell you is only &lt;a href="https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch" rel="noopener noreferrer"&gt;for manual invocations&lt;/a&gt;, meaning someone would have to go to the Actions tab in the repository and click the "Run Workflow" button. It looked like the assumption from the response was that I'd be providing both the author and repo name and it would spit back the number count of &lt;code&gt;state: open&lt;/code&gt; PRs, as detected via &lt;code&gt;octokit/request-action&lt;/code&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  Verdict
&lt;/h5&gt;

&lt;p&gt;This wasn't for my need, so I moved on.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bing Chat
&lt;/h4&gt;

&lt;p&gt;Officially, Microsoft's Bing team acts like Bing Chat is only available from MS Edge. In reality, if you have &lt;a href="https://www.bing.com/search?q=Bing+AI&amp;amp;showconv=1&amp;amp;FORM=hpcodx" rel="noopener noreferrer"&gt;the relevant URL&lt;/a&gt;, you can get to it from presumably any modern web browser. Also, I didn't add this one until after I solved my problems. It was a bit of code that I needed to implement with some urgency. That said, I'm somewhat disappointed I didn't think to check Bing Chat's response at the time, as I rather enjoy that in spite of being written primarily as a BASH script, it makes use of the GitHub API directly to get the data needed and does so with an apparently decent amount of knowledge as to what I was looking for. Here it is after being updated to allow for the label escape.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h5&gt;
  
  
  Verdict
&lt;/h5&gt;

&lt;p&gt;I was intrigued, in spite of having already moved on. Maybe I'll consider checking against Bing in the future, as this seemed the most cohesive and likely to work out of the box. Then again it carries a downside of bing a BASH script at its heart, not a problem per se, but I do spend most of my time in JS/TS/Node and something in that flavor makes it instantly more easy to maintain.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I Concluded Things
&lt;/h3&gt;

&lt;p&gt;Ultimately, I was pressed for time and had to go with the one I felt most comfortable with, the Bard solution. As I mentioned already I had to change things after I realized it didn't do &lt;em&gt;exactly&lt;/em&gt; what I needed to, after having implemented it live; there's nothing like testing in prod as they say. In any case, here's what I came up with in the end. I tried to lean hard into the using the steps as the logic, had to forcibly filter the open PRs so it wouldn't confuse all of those in my repo with the PR author's, set that as output from the step, which I could use to drive the message and fail or succeed steps accordingly. It's not perfect, but I can easily maintain it and it helped a fair amount for the remainder of the month since it went online over &lt;a href="https://github.com/edm00se/awesome-board-games/actions/workflows/limit-prs.yml" rel="noopener noreferrer"&gt;&lt;code&gt;240 workflow runs&lt;/code&gt;&lt;/a&gt;. Here's a copy, otherwise &lt;a href="https://github.com/edm00se/awesome-board-games/blob/65a2f528c076f9d66179d59a7fa152d918a35c6d/.github/workflows/limit-prs.yml" rel="noopener noreferrer"&gt;you can see it where it lives&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Take Aways
&lt;/h3&gt;

&lt;p&gt;Ultimately, I still had to write some of it at the end of the day. I was almost disappointed, but my expectations going into it weren't for anything truly magical. For many it may have been a help to have a starting point, but as someone who's both familiar with writing GitHub Actions and other scripts for automation, I'd call it a bit of an draw since I spent more time debugging what had gone wrong in the example I was given, rather than just writing it myself. In short, my day job is secure, at least for a while.&lt;/p&gt;

&lt;p&gt;Until next time, cheers. ☕️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://edm00se.io/putting-the-bots-to-work/" rel="noopener noreferrer"&gt;Putting The Bots To Work&lt;/a&gt; was originally published at &lt;a href="https://edm00se.io/" rel="noopener noreferrer"&gt;edm00se.io&lt;/a&gt; on 10-November-2023.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
      <category>automation</category>
      <category>bots</category>
    </item>
    <item>
      <title>JSON and Number Formats</title>
      <dc:creator>Eric McCormick</dc:creator>
      <pubDate>Fri, 06 Oct 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/edm00se/json-and-number-formats-18jb</link>
      <guid>https://dev.to/edm00se/json-and-number-formats-18jb</guid>
      <description>&lt;p&gt;I know it's been a while, figured I'd pop up write a quick blog.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5RCm_Trq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://edm00se.io/assets/static/kraken.d042d20.e8e2207fa78b3039802ca3c3fede1a47.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5RCm_Trq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://edm00se.io/assets/static/kraken.d042d20.e8e2207fa78b3039802ca3c3fede1a47.gif" alt="a kraken lifting a sailing ship above water, cracking it in half, and dumping the people into the sea" width="400" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Numbers came up as a topic today, you know, thse primitive entities in JavaScript. Yeah, I was surprised as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Whether this is truly a problem is debatable. Working in an almost exclusively node and TS/JS context these days, my code lives and dies based on what my runtime supports. Usually this is defined by &lt;a href="https://nodejs.dev/en/learn/the-v8-javascript-engine/" rel="noopener noreferrer"&gt;node and its implementation of the v8 engine&lt;/a&gt;. Today this means specifically its implementation of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON" rel="noopener noreferrer"&gt;JSON&lt;/a&gt; and its &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse" rel="noopener noreferrer"&gt;&lt;code&gt;parse&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify" rel="noopener noreferrer"&gt;&lt;code&gt;stringify&lt;/code&gt;&lt;/a&gt; methods. I thought knew about everything there was to know about JSON, short of &lt;a href="https://json5.org/" rel="noopener noreferrer"&gt;JSON 5&lt;/a&gt; which sadly looks like &lt;a href="https://github.com/nodejs/node/issues/40714" rel="noopener noreferrer"&gt;it won't be supported by node anytime soon&lt;/a&gt;, but while unsurprised, I learned something today. The short version is that numeric values in JSON strings need to be valid &lt;code&gt;float&lt;/code&gt;s or &lt;code&gt;int&lt;/code&gt;s, this shouldn't be a surprise to anyone experienced with JavaScript. Where the rubber meets the road is that in the process of &lt;code&gt;JSON.stringify&lt;/code&gt;ing or &lt;code&gt;JSON.parse&lt;/code&gt;ing, any trailing &lt;code&gt;.0&lt;/code&gt; on a numeric value will be stripped. Of course it still is of the correlating value, and if decimal places are needed, you &lt;em&gt;could&lt;/em&gt; pass the value as a string, but that's silly. What's also silly is the inevitable kickback one could get when matching an existing system's output when migrating to a new one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Is This a "Problem"?
&lt;/h3&gt;

&lt;p&gt;As far as I can tell, the previously generated output was coming from a C based runtime that was generating the output with complete abandon for the ultimate JSON output itself. It succeeded in creating a numeric value that was parsable as either a &lt;code&gt;float&lt;/code&gt; or &lt;code&gt;int&lt;/code&gt;, making it technically correct, but mildly unhelpful and an annoyance for me, here &lt;em&gt;in the future&lt;/em&gt;. JavaScript, JSON parse, and JSON stringify will each strip the &lt;code&gt;.0&lt;/code&gt; specificity as its unnecessary for it as a numeric value, either as an &lt;code&gt;int&lt;/code&gt; or &lt;code&gt;float&lt;/code&gt;; it's just not needed and any need to &lt;em&gt;display&lt;/em&gt; the value differently would likely require using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed" rel="noopener noreferrer"&gt;&lt;code&gt;.toFixed&lt;/code&gt;&lt;/a&gt;, because that's a function of display, not numeric value. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ljlm2IhP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://edm00se.io/assets/static/technically-correct.82a2fbd.4f93395593c5d650b97c1990025a3d3e.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ljlm2IhP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://edm00se.io/assets/static/technically-correct.82a2fbd.4f93395593c5d650b97c1990025a3d3e.gif" alt="Futurama GIF showing a lawyer character stating " width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  An Example
&lt;/h3&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/json-and-number-precision-wz8hg2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;When in doubt, check what you know. We'll see whether I need to do some custom string processing or not; preferably the latter. Still, I've gone down &lt;a href="https://edm00se.io/java/custom-json-serilization/" rel="noopener noreferrer"&gt;the custom JSON serialization path before&lt;/a&gt;, but that was on another platform with different tooling and reasons. Until next time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://edm00se.io/json-and-number-formats/" rel="noopener noreferrer"&gt;JSON and Number Formats&lt;/a&gt; was originally published at &lt;a href="https://edm00se.io/" rel="noopener noreferrer"&gt;edm00se.io&lt;/a&gt; on 06-Oct-2023.&lt;/p&gt;

</description>
      <category>development</category>
      <category>web</category>
      <category>json</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Proxying APIs With Parcel v2!</title>
      <dc:creator>Eric McCormick</dc:creator>
      <pubDate>Thu, 05 Aug 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/edm00se/proxying-apis-with-parcel-v2-4bo5</link>
      <guid>https://dev.to/edm00se/proxying-apis-with-parcel-v2-4bo5</guid>
      <description>&lt;p&gt;It's no secret I've been a fan of &lt;a href="https://parceljs.org/" rel="noopener noreferrer"&gt;Parcel&lt;/a&gt; for some time. As a bundler, it's taken what's best about webpack and made it more friendly towards end users, uses more sane defaults, and allowed for some really powerful adaptations that would otherwise not be incredibly available. Previously I've blogged about the ease of setting up a local proxy to use with parcel, so that any back-end components can have their traffic accordingly directed. There's an update now with &lt;a href="https://v2.parceljs.org/blog/rc0/" rel="noopener noreferrer"&gt;the v2 release candidate available&lt;/a&gt;, so I figure it's worth talking about again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parcel v2 RC
&lt;/h3&gt;

&lt;p&gt;The release candidate is exciting to me as it is the culmination of a couple years worth of alpha and beta releases. To their great credit, the parcel team did not rush the release candidate, which seems awfully tempting these days. If you're looking to get started or read up in their documentation, I recommend it. Just pointing your application's &lt;code&gt;package.json&lt;/code&gt; towards a given target seems to be all the magic sauce required these days, and that's impressive with their many out of the box features and default support.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://v2.parceljs.org/" rel="noopener noreferrer"&gt;v2.parceljs.org&lt;/a&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  Previously...
&lt;/h3&gt;

&lt;p&gt;Previously, what was required to proxy api calls to say &lt;code&gt;/api&lt;/code&gt; involved writing a thin node script implementation, making use of &lt;code&gt;http-proxy&lt;/code&gt; and directing any traffic matching your api endpint's starting path, like &lt;code&gt;/api&lt;/code&gt;, and forwarding the rest to parcel's local dev server. The parcel api made this all possible from a single script file, so to me it was a great win for power and simplicity. It also took slightly more effort up front, but was a relatively lean implementation of a development dependency. Ideally this is something that would live in a configuration and not an application script, which is exactly what the parcel team seemed to think.&lt;/p&gt;

&lt;h3&gt;
  
  
  Doing It With v2
&lt;/h3&gt;

&lt;p&gt;You can read &lt;a href="https://v2.parceljs.org/features/development/#api-proxy" rel="noopener noreferrer"&gt;the documentation here&lt;/a&gt;, as they have a page on just this topic, but the short version is to do two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;install a middleware package alongside your other dev dependencies
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --develop http-proxy-middleware
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;generate a &lt;code&gt;.proxyrc&lt;/code&gt; configuration, like so:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#.proxyrc
{
  "/api": {
    "target": "http://localhost:8000/",
    "pathRewrite": {
      "^/api": ""
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, any requests with a path starting with &lt;code&gt;/api&lt;/code&gt; now will be forwarded to &lt;code&gt;localhost:8000&lt;/code&gt;. That's pretty simple and incredibly useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jumping In Now
&lt;/h3&gt;

&lt;p&gt;If you've been away from front-end tooling for a little while, the landscape has predictably changed again. If you're looking to get started, I'd recommend having a look at either &lt;a href="https://v2.parceljs.org/" rel="noopener noreferrer"&gt;Parcel v2&lt;/a&gt; or &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;. These are the two big contenders I'm tracking that make use of some interesting and modern tooling that makes for some powerful and friendly developer experiences. I won't dive into those and their differences here, but they're worth the look.&lt;/p&gt;

&lt;p&gt;Happy coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://edm00se.io/web/proxying-apis-with-parcel-v2/" rel="noopener noreferrer"&gt;Proxying APIs With Parcel v2!&lt;/a&gt; was originally published at &lt;a href="https://edm00se.io/" rel="noopener noreferrer"&gt;edm00se.io&lt;/a&gt; on 05-Aug-2021.&lt;/p&gt;

</description>
      <category>web</category>
      <category>tooling</category>
      <category>proxy</category>
      <category>parcel</category>
    </item>
    <item>
      <title>Side Benefits of Static Typing</title>
      <dc:creator>Eric McCormick</dc:creator>
      <pubDate>Fri, 08 Nov 2019 18:47:00 +0000</pubDate>
      <link>https://dev.to/edm00se/side-benefits-of-static-typing-ihj</link>
      <guid>https://dev.to/edm00se/side-benefits-of-static-typing-ihj</guid>
      <description>&lt;p&gt;Regardless of your being for or against statically typing and transpiling your JavaScript code, there are advantages to doing so. No system is absolute and yes, it does transpile into JavaScript proper. That said, there can be a great number of conveniences brought in by typing your JS source code. The most obvious major reasos is that, properly defined, your models, API use, and function input and output will be consistently to an expected format. This addresses one of the largest complaints about JavaScript as a language, that everything is so &lt;a href="https://m-w.com/dictionary/loosey-goosey" rel="noopener noreferrer"&gt;loosey-goosey&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O2jNoj3v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://edm00se.io/assets/images/post_images/untitledGoose.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O2jNoj3v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://edm00se.io/assets/images/post_images/untitledGoose.png" alt="good news everyone" width="250" height="250"&gt;&lt;/a&gt;The titular antihero and miscreant of the &lt;a href="https://goose.game/" rel="noopener noreferrer"&gt;Untitled Goose Game&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Beyond this primary advantage, there are a good number of side benefits to using a static typed system in front of your JavaScript code base.&lt;/p&gt;

&lt;h3&gt;
  
  
  Side benefits
&lt;/h3&gt;

&lt;p&gt;Adding static typing to your JavaScript, such as with TypeScript, brings with it a couple of concepts by the sheer nature of the fact that there’s a build phase of the source code to create the ultimately consumed JavaScript. This would happen the same if we used a build tool and &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;babel&lt;/a&gt; to process JavaScript, so while it’s not entirely unique to add to the process around JS, it carries with it some benefits as well.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pre-Processing
&lt;/h4&gt;

&lt;p&gt;By merely having a build phase in the life cycle of an application, we can do a number of things to ease our concerns. We can create config files for different environments, allowing for the different setups or variable inclusions based on environment. This can be done a number of different ways, such as keeping different &lt;code&gt;.env&lt;/code&gt; files containing their respective values or having a &lt;code&gt;config.js&lt;/code&gt; file which resolves an object with its respective variables through a single object interface. Whichever route you take, having this as a pluggable constant in your application helps take the guesswork out of things.&lt;/p&gt;

&lt;p&gt;We can also abbreviate or mock different integrations or even down to the function level, for the purposes of testing. A testing environment is after all just another environment. This makes scaffolding a bit more self-explanatory as well, thankfully. Most test runners, &lt;a href="https://jestjs.io/docs/en/24.0/getting-started.html#using-babel" rel="noopener noreferrer"&gt;such as jest, flag the node environment variable (a la &lt;code&gt;process.env.NODE_ENV&lt;/code&gt;) to &lt;code&gt;test&lt;/code&gt; during its run&lt;/a&gt;, so setting your testing configuration as &lt;em&gt;just another environment&lt;/em&gt; is not only well supported, but desirable.&lt;/p&gt;

&lt;h4&gt;
  
  
  Compilation / Transpilation
&lt;/h4&gt;

&lt;p&gt;The names of things matter, but when it comes to something processing what is or will be JavaScript I have given up on caring &lt;em&gt;too much&lt;/em&gt;. There’s a difference, I just don’t care to get into it here. TypeScript relies on their compiler &lt;code&gt;tsc&lt;/code&gt; to compile source into browser consumable JavaScript, so with TS feel free to use the word “compile”. If you happen to use the term ‘transpile’, since that’s what happens with babel and other JavaScript tooling, I will treat you as having said the correct thing, even though there may be some difference in the nuance of what’s going on under the hood. It’s sort of like “Merry Christmas”, “happy holidays”, “happy Kwanzaa”, and more. Most people celebrate &lt;em&gt;something&lt;/em&gt; around the end of the year, prior to the new year, and if we all want to live healthier and happier lives, we won’t take offense to whatever it is someone wishes us. For bonus points, turn it into a game and see how many varied phrases you can “collect” receipt of by others to tally up after the completion of the holiday rush. No, the points don’t actually matter, like Who’s Line.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Side Benefits
&lt;/h4&gt;

&lt;p&gt;Some of the key side benefits to static typing in your work flow seem to come in a couple of flavors.&lt;/p&gt;

&lt;h5&gt;
  
  
  Better Editor / Tooling
&lt;/h5&gt;

&lt;p&gt;VS code is my primary editor for front-end work. One of the features it brings, by default, is what it calls &lt;a href="https://code.visualstudio.com/docs/editor/intellisense" rel="noopener noreferrer"&gt;IntelliSense&lt;/a&gt;. As far as I’m concerned, it’s implemented nearly seamlessly and is a great feature for editing with JavaScript or TypeScript. It offers a high degree of awareness regarding code, be it your source or imported from &lt;code&gt;node_module&lt;/code&gt;s, as well as a type-ahead completion suggestions that are pretty solid. With static types in use, this also means that there is a far more intelligent display of what is expected. As someone who has done a large amount of Java work previously, this fills the gap of some of what I felt was missing when focusing more on front-end work, without Eclipse / IntelliJ IDEA.&lt;/p&gt;

&lt;p&gt;Additionally, this greater and true understanding of imported code means that things like tree shaking and code splitting are far more powerful, as knowing explicitly, via named imports/exports, whether a function is needed in the built output is now legitimately definitive. This capability has obvious advantages regarding breaking apart modern front-end heavy builds and pushing an increasingly aware amount of what’s needed “down the pipes” to the user based on things like which page they’re on or whether or not they’re even logged into a valid session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Over the last year, I’ve been increasing my use of TypeScript in my day-to-day work and have considered incorporating it more into my open source and dabbling projects. The best part of it all is that having created &lt;a href="https://github.com/edm00se/vue-parcel-starter" rel="noopener noreferrer"&gt;my own preferred flavor of a starter repo&lt;/a&gt; makes this easy to test in a branch and the use of my preferred build tool, &lt;a href="https://parceljs.org/" rel="noopener noreferrer"&gt;Parcel&lt;/a&gt;, makes this &lt;a href="https://github.com/edm00se/vue-parcel-starter/pull/61/files#diff-60b2029a3ac639f9ff664d542400700aR10" rel="noopener noreferrer"&gt;extremely easy to setup and try out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, do you &lt;em&gt;need&lt;/em&gt; to use TypeScript or another static typing solution in your JavaScript? No, you can write perfectly valid JS without it. What I do ask myself has to do far more with whether I want to skip out on some of what TS can give me, without any additional effort. I’m sure you’ll find your own answer, but hopefully I’ve inspired a little extra consideration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus
&lt;/h3&gt;

&lt;p&gt;As mentioned above, adding TS to my starter repo was easy, almost too easy. When tooling does what it should, it can lead us to great places. Here’s how easy it was.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VexeVu-d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://edm00se.io/assets/images/post_images/addingTypeScript.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VexeVu-d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://edm00se.io/assets/images/post_images/addingTypeScript.gif" alt="live parcel dev server detects changes, installs typescript dep, new build is good" width="800" height="406"&gt;&lt;/a&gt;adding typescript to vue components with parcel, stupid easy &lt;/p&gt;

&lt;p&gt;&lt;a href="https://edm00se.io/web/side-benefits-of-static-typing/" rel="noopener noreferrer"&gt;Side Benefits of Static Typing&lt;/a&gt; was originally published by at &lt;a href="https://edm00se.io" rel="noopener noreferrer"&gt;Dev|Blog&lt;/a&gt; on November 08, 2019.&lt;/p&gt;

</description>
      <category>web</category>
      <category>typescript</category>
      <category>parcel</category>
    </item>
    <item>
      <title>Maintaining Hacks and Moving On From AMP</title>
      <dc:creator>Eric McCormick</dc:creator>
      <pubDate>Fri, 23 Aug 2019 16:51:01 +0000</pubDate>
      <link>https://dev.to/edm00se/maintaining-hacks-and-moving-on-from-amp-4pij</link>
      <guid>https://dev.to/edm00se/maintaining-hacks-and-moving-on-from-amp-4pij</guid>
      <description>&lt;p&gt;Note: this post is cross-posted from my blog, originally posted 22-Aug-2019, and generally deals with some theory and approach, with a use case of an AMP based site's hacks as a central idea. You can find the original post here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://edm00se.io/web/maintaining-hacks/" rel="noopener noreferrer"&gt;https://edm00se.io/web/maintaining-hacks/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Writing a hacky bit of software to "make something work" is rarely anything a developer wishes to do. They're &lt;del&gt;crimes&lt;/del&gt; acts of necessity, born of the moment. True innovation exists within the &lt;strong&gt;need&lt;/strong&gt; to achieve a task, but sometimes we merely do what we need to do to get the job done. This post exemplifies one such effort on my part, along with my further efforts to keep the madness at bay.&lt;/p&gt;

&lt;h3&gt;
  
  
  In Case You've Been Living Under A Rock
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://amp.dev/" rel="noopener noreferrer"&gt;AMP&lt;/a&gt; (Accelerated Mobile Pages), for those of you who have blissfully avoided it, sometimes gets a bad reputation. Some of the primary criticisms against AMP include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it ignores and bypasses most web conventions

&lt;ul&gt;
&lt;li&gt;requiring a large-ish amount of JavaScript files from Google&lt;/li&gt;
&lt;li&gt;the scripts to load are hosted purely by Google&lt;/li&gt;
&lt;li&gt;the scripts can change at any time and are un-versioned, are maintained by Google&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;effectively creates vendor lock-in for the format&lt;/li&gt;

&lt;li&gt;has that bar over the top of the screen, when viewed on mobile, which cannot be removed

&lt;ul&gt;
&lt;li&gt;there was a bit of an uproar a little while back as something went wrong and the link wasn't clickable and it couldn't be removed or fixed by anyone else&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Just to be clear, it isn't all doom and gloom. There's a reason I tried AMP out on this very blog in the first place. What it achieves is somewhat impressive, even if it bumps most web convention norms. For a content-focused site, it succeeds in keeping the focus on the content. This includes in limiting what ads can do and how they're displayed. Gone are the multiple pop ups asking to put you on a mailing list or auto playing videos, for the most part. It also limits how much JavaScript can be loaded, to be a valid AMP site; just that which loads the site, none of which is allowed for AMP compliant pages. &lt;a href="https://validator.ampproject.org/#url=https%3A%2F%2Fedm00se.io%2Fsearch%2F" rel="noopener noreferrer"&gt;This blog's search page does not validate&lt;/a&gt; per the AMP spec. While this is annoying for web app developers, it's great for content as a consumer, because there's less for developers to fiddle around with.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Hacks In Question
&lt;/h3&gt;

&lt;p&gt;The involved hacks are ultimately mechanisms for displaying content that requires JavaScript to load. In both cases, from a third party source. Specifically this is relating to both GitHub gist embeds and Disqus comments. The part that made these become hacks is that AMP's requirements for JS are that it can be loaded, but not from the host site. This leads us to the route of embedding content via an &lt;code&gt;iframe&lt;/code&gt;; specifically AMP's &lt;a href="https://amp.dev/documentation/components/amp-iframe/" rel="noopener noreferrer"&gt;&lt;code&gt;amp-iframe&lt;/code&gt;&lt;/a&gt; implementation, as they use unique namespaces for components.&lt;/p&gt;

&lt;p&gt;In my case, I wrote a pair of HTML pages that contained some JavaScript with some logic to take passed URL query parameters to determine what to load in the generated &lt;code&gt;iframe&lt;/code&gt; for the destination&lt;/p&gt;

&lt;p&gt;note: The gist workaround is no longer needed, as AMP eventually added this as a native component some time after I did my work around. Also of note, the disqus solution I came to loads their JS, which loads another nested &lt;code&gt;iframe&lt;/code&gt;; if you parse their query parameter logic you could possibly do without a middleman, although this was not clear when I began as it was a new technique with little documentation at the time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keeping The Madness
&lt;/h3&gt;

&lt;p&gt;At first, I just picked a domain name I already owned and controlled and knew I could park a pair of HTML files into without impacting the site. In the case of Disqus, I had to allow the new domain as authorized to interact with my connected account. While this did the job, it lacked in the sense of holding to its purpose and was moving with an unrelated codebase. Preparing to move off that domain meant I would need to deal with things properly. My solution involved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;moving the hack pages to a new home

&lt;ul&gt;
&lt;li&gt;in my case I wound up using a GitHub repository with the pages deployed via GitHub Pages&lt;/li&gt;
&lt;li&gt;this is free, worked with my existing custom domain name for my root GitHub Pages (user site), and meant it was merely &lt;code&gt;&amp;lt;my domain&amp;gt;/amp-hacks&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;updating existing references

&lt;ul&gt;
&lt;li&gt;updating my AMP site (blog) to point to the new destination (a simple replace of domain/path from the old one to the new one)&lt;/li&gt;
&lt;li&gt;updating Disqus as to the authorized domain access&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;testing it out

&lt;ul&gt;
&lt;li&gt;this went strangely without a hiccup, hooray! 🎉&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Where is it now? If you're interested, you can check out my repository, &lt;a href="https://github.com/edm00se/amp-hacks" rel="noopener noreferrer"&gt;&lt;code&gt;github.com/edm00se/amp-hacks&lt;/code&gt;&lt;/a&gt;. Feel free to check it out, see what it does, or fork it and make it your own; or stare in horror at the workaround needed. For reference the repository is new, but the pages date back to about 3 years ago in a different repo I've since archived; I finally stuffed my hacks into their own box.&lt;/p&gt;

&lt;p&gt;That's it, the big reveal. Have hacks that are needed to make things work? Throw them in their own box and keep them, documented and available, but isolated. One day they can be removed and the world will be a little bit brighter for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Leading Question
&lt;/h3&gt;

&lt;p&gt;When your "normal" development practice &lt;em&gt;requires&lt;/em&gt; use of hacks, as the &lt;code&gt;amp-iframe&lt;/code&gt; has been required/used by many to solve issues since AMP's creation, what does that mean for desirability of development for that platform? If a normal requirement, such as a site specific search page which isn't just a form to submit a Google site search, is just unattainable, then it's not a viable development platform. This is where I've arrived, which is to regard AMP as a great way of content consumption, but not as a platform to develop for. I could continue to live with my blog in its current format, it works, and does so pretty well. I'm just moving on.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's To Come
&lt;/h3&gt;

&lt;p&gt;I've dabbled over the last year, give or take, in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vuepress.vuejs.org/" rel="noopener noreferrer"&gt;vuepress&lt;/a&gt;, because I love vue.js and its documentation is pretty hot&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;gatsby&lt;/a&gt;, because the web dev scene has gone gatsby crazy&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://gridsome.org/" rel="noopener noreferrer"&gt;gridsome&lt;/a&gt;, because I love vue.js and it's the most gatsby-like analogue with vue&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.11ty.io/" rel="noopener noreferrer"&gt;eleventy&lt;/a&gt;, because while the world doesn't need yet another static site generator, it's aim is close to jekyll, all while being an unobtrusive build system&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;svelte&lt;/a&gt;, because I love JS, but also love extreme simplicity; this isn't an SSG, but rather an application framework with a focus on low code, reactivity, and no virtual DOM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm not sure where I'm going with this blog, but considering my obsession over development tooling and the frequency with which I overhaul my blog as an excuse to try out something new, I can't help but imagine it's only a matter of some time before it happens. It's already been about &lt;a href="https://edm00se.io/admin/reincarnation/" rel="noopener noreferrer"&gt;three years in this format&lt;/a&gt;, so it's probably time to reincarnate it again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;All in all, AMP has its place, but it's not for me. I don't think it's evil, it just prevents my usual playing with things, so as a developer and not a content manager, it's time for me to move on. Also, this post isn't about the specifics of my solutions; merely about what insanity it was and the improved way I eventually settled on handling the hackery. Initially, it was just an extra couple of pages parked in a deployed domain I owned and controlled, but finally I was able to park them in a dedicate space and will serve its purpose until it's no longer needed.&lt;/p&gt;

</description>
      <category>web</category>
      <category>amp</category>
      <category>hacks</category>
    </item>
    <item>
      <title>Greetings</title>
      <dc:creator>Eric McCormick</dc:creator>
      <pubDate>Wed, 22 Feb 2017 16:23:58 +0000</pubDate>
      <link>https://dev.to/edm00se/greetings</link>
      <guid>https://dev.to/edm00se/greetings</guid>
      <description>&lt;p&gt;I have been coding for over 8 years professionally, with occasional freelance front-end, PHP, and WordPress work prior to that.&lt;/p&gt;

&lt;p&gt;You can find me &lt;a href="https://twitter.com/edm00se" rel="noopener noreferrer"&gt;on Twitter as @edm00se&lt;/a&gt; and &lt;a href="https://github.com/edm00se" rel="noopener noreferrer"&gt;on GitHub with the same handle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I &lt;a href="https://edm00se.io" rel="noopener noreferrer"&gt;blog on my development concerns&lt;/a&gt;, which entails concerns across a variety of interests, from my day job to my personal projects. I love Node.js, CI/CD, Docker, virtually all automation, and git.&lt;/p&gt;

&lt;p&gt;If you want to ask me something, you can can &lt;a href="https://github.com/edm00se/ama" rel="noopener noreferrer"&gt;Ask Me (nearly) Anything&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
