<?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: Evan K</title>
    <description>The latest articles on DEV Community by Evan K (@evanskaufman).</description>
    <link>https://dev.to/evanskaufman</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%2F451085%2Feb569c3c-28df-4144-bcb3-be61f097a004.jpg</url>
      <title>DEV Community: Evan K</title>
      <link>https://dev.to/evanskaufman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/evanskaufman"/>
    <language>en</language>
    <item>
      <title>Supporting multiple Javascript environments</title>
      <dc:creator>Evan K</dc:creator>
      <pubDate>Fri, 25 Jul 2025 00:01:09 +0000</pubDate>
      <link>https://dev.to/evanskaufman/supporting-multiple-javascript-environments-3f14</link>
      <guid>https://dev.to/evanskaufman/supporting-multiple-javascript-environments-3f14</guid>
      <description>&lt;p&gt;I've been working on a small utility that I've recently &lt;a href="https://www.npmjs.com/package/serialize-function" rel="noopener noreferrer"&gt;published to npm&lt;/a&gt;, and my goal with it was to target both a Node.js and a browser environment.&lt;/p&gt;

&lt;p&gt;In order to accomplish this, I picked up a tool that I've been loathe to touch since the last time I used it, roughly a decade ago — &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;Babel&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's wrong with Babel?
&lt;/h2&gt;

&lt;p&gt;While I wouldn't actually say there's something &lt;em&gt;wrong&lt;/em&gt; with Babel, it does (necessarily) involve lots of complexity. It can be an absolute &lt;em&gt;nightmare&lt;/em&gt; to configure, depending on your build process(es).&lt;/p&gt;

&lt;p&gt;For this relatively simple project, within the space of a week and a half, I wrote, then threw away and rewrote my babel build configuration several times until I was satisfied with the end result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then why use a transpiler at all?
&lt;/h2&gt;

&lt;p&gt;When used correctly, a build process that involves transpilation can strike the sweet spot where you're able to use the latest ECMAScript features while maintaining backward compatibility with a variety of target environments.&lt;/p&gt;

&lt;p&gt;In my case, I wanted to be able to write my source code using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules" rel="noopener noreferrer"&gt;ES Modules&lt;/a&gt; that enjoy widespread browser support, while compiling down to the &lt;a href="https://nodejs.org/docs/latest-v16.x/api/modules.html#modules-commonjs-modules" rel="noopener noreferrer"&gt;CommonJS&lt;/a&gt; module system that's still widely used in Node.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show, don't tell
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Full disclaimer: while this is the result of a lot of trial and error, I don't claim to have met any standard of best practices, and would recommend you do your own homework. Decide what best meets your needs, rather than just following my (or anyone else's) example.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Start to finish, &lt;a href="https://github.com/EvanK/npm-serialize-function/blob/f02fd7d327968c00e86a60e35cb4154c22fd71d9/package.json#L29" rel="noopener noreferrer"&gt;my build process&lt;/a&gt; consists of a some nested npm run scripts and a decent amount of bash:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dist&lt;/code&gt;&lt;/strong&gt;: kicks off additional run scripts per build target

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;build-browser&lt;/code&gt;&lt;/strong&gt;: prepares the browser distributable by way of...

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;concat-browser&lt;/code&gt;&lt;/strong&gt;: concatenates a few source files together into a single &lt;code&gt;build-main-browser.mjs&lt;/code&gt; script&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;transpile-browser&lt;/code&gt;&lt;/strong&gt;: runs babel on said script with the &lt;a href="https://github.com/EvanK/npm-serialize-function/blob/main/.babelrc.esm.json" rel="noopener noreferrer"&gt;&lt;code&gt;.babelrc.esm.json&lt;/code&gt;&lt;/a&gt; config and an output filename&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;&lt;code&gt;build-node&lt;/code&gt;&lt;/strong&gt;: prepares the node distributable by way of...

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;concat-node&lt;/code&gt;&lt;/strong&gt;: concatenates a few source files together into a single &lt;code&gt;build-main-node.mjs&lt;/code&gt; script&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;transpile-node&lt;/code&gt;&lt;/strong&gt;: runs babel on said script with the &lt;a href="https://github.com/EvanK/npm-serialize-function/blob/main/.babelrc.cjs.json" rel="noopener noreferrer"&gt;&lt;code&gt;.babelrc.cjs.json&lt;/code&gt;&lt;/a&gt; config and an output filename&lt;/li&gt;
&lt;li&gt;bash snippet that copies &lt;code&gt;import.mjs&lt;/code&gt; for ESM export/import support on top of the transpiled CJS&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This produces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a browser targeted script in &lt;code&gt;lib/&lt;/code&gt; with the original ES Module exports, leveraging a &lt;a href="https://browsersl.ist/" rel="noopener noreferrer"&gt;browserslist&lt;/a&gt; query for which browser features to transpile support for&lt;/li&gt;
&lt;li&gt;a Node v20 targeted script in &lt;code&gt;dist/&lt;/code&gt; transpiled down to CommonJS, with an additional script to tack on ES Module exports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see the result &lt;a href="https://www.npmjs.com/package/serialize-function?activeTab=code" rel="noopener noreferrer"&gt;on npm&lt;/a&gt;, if you're interested.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>browser</category>
      <category>babel</category>
    </item>
    <item>
      <title>Stringifying Errors: A Uniquely Javascript Problem</title>
      <dc:creator>Evan K</dc:creator>
      <pubDate>Sun, 29 Sep 2024 00:30:13 +0000</pubDate>
      <link>https://dev.to/evanskaufman/stringifying-errors-a-uniquely-javascript-problem-12b</link>
      <guid>https://dev.to/evanskaufman/stringifying-errors-a-uniquely-javascript-problem-12b</guid>
      <description>&lt;p&gt;Exception handling, like most things in the Javascript world, is...complicated.&lt;/p&gt;

&lt;p&gt;What is or isn't supported may vary widely between client (browser) and server (NodeJS), and further even from one browser to another.&lt;/p&gt;

&lt;p&gt;If you're not too familiar already, &lt;a href="https://dev.to/valentinogagliardi/a-mostly-complete-guide-to-error-handling-in-javascript-min"&gt;this is a great guide to all things Javascript error handling&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The short version goes like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exception handling typically involves &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw" rel="noopener noreferrer"&gt;throwing&lt;/a&gt; and catching exceptions, either synchronously (in a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch" rel="noopener noreferrer"&gt;try...catch&lt;/a&gt; block) or asynchronously (with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch" rel="noopener noreferrer"&gt;Promise.prototype.catch&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Javascript provides a standard built-in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error" rel="noopener noreferrer"&gt;Error&lt;/a&gt; class for you to use, either directly or with extending sub-classes.&lt;/li&gt;
&lt;li&gt;The standard Error class comes with useful but not-always-supported (and so not-always-used) features like the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stack" rel="noopener noreferrer"&gt;stack&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause" rel="noopener noreferrer"&gt;cause&lt;/a&gt; properties.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw" rel="noopener noreferrer"&gt;throw&lt;/a&gt; statement allows you to throw a &lt;em&gt;user-defined exception&lt;/em&gt;, which is notably &lt;strong&gt;not required to be an Error object&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Error class
&lt;/h2&gt;

&lt;p&gt;Error objects are great, but the biggest headache around handling them typically involves stringifying or serializing them, as is evident from this NodeJS console example:&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a problem occurred&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error: a problem occurred&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a problem occurred&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The error &lt;em&gt;object&lt;/em&gt; in question — an instance of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error" rel="noopener noreferrer"&gt;Error&lt;/a&gt; class — supports conversion to a string via its &lt;code&gt;toString&lt;/code&gt; method. This produces (essentially) a concatenation of the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;message&lt;/code&gt;, omitting the stack and any other instance properties. Sometimes this is good, as you just want to know &lt;em&gt;what&lt;/em&gt; broke but not necessarily &lt;em&gt;where&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Serialization to JSON is decidedly unhelpful, returning an empty object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging to different destinations
&lt;/h2&gt;

&lt;p&gt;For debugging and most logging purposes, the built-in &lt;code&gt;console.log&lt;/code&gt; method prints a friendly and verbose summation of any error directly to stdout (in NodeJS), or to the web console (in browser):&lt;br&gt;
&lt;a href="https://media2.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%2F5ythl1hfv9zy7zwhg2pp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F5ythl1hfv9zy7zwhg2pp.png" alt="side by side of node.js and browser console.logs of an error object" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if instead you need it printed to stderr, look no further than the &lt;code&gt;console.error&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Well, what if you need to log an error somewhere else? To a file, a database table, a third party logging utility, etc.&lt;/p&gt;

&lt;p&gt;You might wonder if there's a way to capture this same output from the console to a string variable, and in NodeJS you technically could. It is not simple, however, and one approach requires &lt;a href="https://nodejs.org/docs/latest-v18.x/api/console.html#new-consolestdout-stderr-ignoreerrors" rel="noopener noreferrer"&gt;another console instance&lt;/a&gt; and some trickery with streams.&lt;/p&gt;

&lt;p&gt;Streams give me anxiety, so I went another way.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enter &lt;a href="https://www.npmjs.com/package/loggable-error" rel="noopener noreferrer"&gt;&lt;code&gt;loggable-error&lt;/code&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A little over two kilobytes of javascript, with &lt;em&gt;zero&lt;/em&gt; runtime package dependencies and a single default export.&lt;/p&gt;

&lt;p&gt;It produces a string approximate to what &lt;code&gt;console.log&lt;/code&gt; would print — an Error object expanded to constructor name, message and stack, with any other instance properties in an object notation:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;stringify&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loggable-error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&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;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&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;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;extra&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="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testing one two three&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="na"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;the actual root cause&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="na"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&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="s1"&gt;some extra debugging info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mf"&gt;3.14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&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;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;e&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&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;e&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="cm"&gt;/* =&amp;gt;
Error: testing one two three
    at file:///home/jdoe/test.js:11:11
    at ModuleJob.run (node:internal/modules/esm/module_job:222:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:123:5) {
  [cause]: CustomError: the actual root cause
      at file:///home/jdoe/test.js:14:20
      at ModuleJob.run (node:internal/modules/esm/module_job:222:25)
      at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
      at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:123:5) {
    [extra]: {"message":"some extra debugging info","values":[3.14,42,null]}
  }
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As shown above, it also handles error objects nested as properties with recursive calls to itself, indenting them at the appropriate level.&lt;/p&gt;

&lt;h3&gt;
  
  
  You've got &lt;code&gt;options&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Because different situations call for different formatting, the exported function accepts a second &lt;code&gt;options&lt;/code&gt; object, allowing you to toggle display of stack traces and control the initial indentation:&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;// shown here with the default options&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;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;stack&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  That's all, folks!
&lt;/h2&gt;

&lt;p&gt;The goal here was to keep it simple, but if you have issues or feature requests, I'd love to hear them.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
    </item>
  </channel>
</rss>
