<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nick Maloney</title>
    <description>The latest articles on Forem by Nick Maloney (@ngmaloney).</description>
    <link>https://forem.com/ngmaloney</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%2F838847%2F3e94b8bd-7ac7-4e58-a012-fea37f0564c4.png</url>
      <title>Forem: Nick Maloney</title>
      <link>https://forem.com/ngmaloney</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ngmaloney"/>
    <language>en</language>
    <item>
      <title>Anything Can be Used for File Storage if You Use it Wrongly Enough</title>
      <dc:creator>Nick Maloney</dc:creator>
      <pubDate>Mon, 31 Jul 2023 19:32:43 +0000</pubDate>
      <link>https://forem.com/thegnarco/anything-can-be-used-for-file-storage-if-you-use-it-wrongly-enough-1hb</link>
      <guid>https://forem.com/thegnarco/anything-can-be-used-for-file-storage-if-you-use-it-wrongly-enough-1hb</guid>
      <description>&lt;p&gt;I recently came across the most excellent blog post “&lt;a href="https://xeiaso.net/blog/anything-message-queue"&gt;Anything can be a message queue if you use it wrongly enough&lt;/a&gt;” (It is a fun read and I highly recommend checking it out). After reading it, it dawned on me that I recently created an abomination that essentially did the inverse, I used a “message queue” (if you would please indulge me in considering Redis one) as a semi-ephemeral file storage service. &lt;em&gt;Please do not use this for production, you have been warned!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In building out a proof-of-concept for some fun with Machine Learning (ML) audio processing, I needed a quick, easy way to store processed files. One of the challenges was that files required multiple processing steps across different services so local file storage was not the best option. The ideal solution would be to use something like S3, but given this was purely a proof of concept (POC) and being a lazy developer, I was looking for something simple and easy. The processing was happening via the most excellent &lt;a href="https://dramatiq.io/"&gt;Dramatiq&lt;/a&gt; library, which uses Redis. This got me thinking that Redis is actually pretty well suited for this use case; it stores binary data well, is relatively fast, is quite stable AND by using expiration param in &lt;code&gt;SET&lt;/code&gt; it would handle house cleaning of old files. &lt;/p&gt;

&lt;p&gt;For the sake of this example, we’ll create a simple Flask application that handles &lt;code&gt;POST&lt;/code&gt; requests for file uploads and saves them to Redis, using a &lt;code&gt;sha256&lt;/code&gt; of the payload as the key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;send_file&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;base64&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;magic&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mimetypes&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;redis&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;encoded_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoded_file&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;expiration_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoded_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expiration_time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example above will save the data to Redis and return the key. It sets the file to expire in 24 hours. &lt;/p&gt;

&lt;p&gt;To retrieve the files, we’ll use a few utilities for attempting to determine mime-type/extension of the saved files and use Flask’s &lt;code&gt;send_file&lt;/code&gt; method for the response.&lt;/p&gt;

&lt;p&gt;Using that endpoint, &lt;code&gt;GET&lt;/code&gt; requests made to &lt;code&gt;/sha_of_file&lt;/code&gt; will return the file, with the appropriate mime-type/extension.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/&amp;lt;key&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;encoded_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;encoded_file&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"File not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;
  &lt;span class="n"&gt;decoded_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b64decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoded_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;mimetype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;magic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoded_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;file_extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mimetypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;guess_extension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mimetype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;temp_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;file_extension&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;

  &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'wb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;temp_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;temp_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoded_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;send_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mimetype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mimetype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;as_attachment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and there you have it. This ended up working quite well for an audio processing pipeline, quickly and easily being able to send audio files exceeding 100mb. The Dramatiq library has the concept of storing results between tasks baked in, but doesn’t solve for sending results back over the wire to the browser. Again, do not use this in a production app, but I would absolutely use this technique again for future POC projects.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Gnarly Technology Predictions for 2022</title>
      <dc:creator>Nick Maloney</dc:creator>
      <pubDate>Wed, 23 Mar 2022 02:02:31 +0000</pubDate>
      <link>https://forem.com/thegnarco/gnarly-technology-predictions-for-2022-cj</link>
      <guid>https://forem.com/thegnarco/gnarly-technology-predictions-for-2022-cj</guid>
      <description>&lt;p&gt;When we first started The Gnar Company I expected to spend a significant amount of time researching and implementing new technologies each year. What we’ve generally found is while new frameworks and stacks are constantly evolving, clients typically seek expertise and stability within a given tech ecosystem. In our 6 years of operating The Gnar we haven’t witnessed any major new frameworks/platforms get released and subsequently dominate the marketplace. If anything, we’ve seen more fragmentation, particularly in the NodeJS ecosystem.&lt;/p&gt;

&lt;p&gt;Below is a quick summary of the technologies our shop will focus on using in 2022:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;React will continue to remain the dominant JS library for UI in 2022. While there are a lot of promising contenders in the space (Svelte, Vue, Preact) there is simply too much momentum behind React for many larger organizations and consultancies to pursue other JS UI libs. Our entire team is proficient in React and we have extensive expertise building very complicated applications in React and we’ve been pleased with the continuous improvement in tooling.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://reactnative.dev/"&gt;React Native&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;React Native (RN) will continue to be our go-to tool for building mobile apps. Given our team's strong proficiency in React, it allows us to build on that knowledge and produce some great apps that are indistinguishable from native mobile apps. We also understand its limitations and will select RN only when it makes sense and recommend native when it doesn’t. Overall, mobile tooling is fickle and it changes even within the native ecosystems (ex: objective C &amp;gt; Swift, Java &amp;gt; Kotlin). Given those changes, I still don’t see a contender to supplant RN in 2022 but we are excited about some newer tech on the horizon like Strada.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://rubyonrails.org/"&gt;Rails&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Rails continues to surprise and impress me. There still isn’t another platform that we’ve found that can deliver the amount of features Rails provides out of the box while being easy to develop in and stable from an operations/maintenance perspective. We have projects that are well past the 5 year mark and they are rock solid - requiring very little maintenance aside from the occasional gem updates. Client demand for skilled Ruby/Rails developers has actually increased for us over the last few quarters. The Rails community and ecosystem is still very active so it will remain a tool our team reaches for.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://stimulus.hotwired.dev/"&gt;Stimulus&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Stimulus is another technology that has surprised me. When it initially came out, its usefulness wasn’t immediately apparent to me as we were heavily entrenched in React. What we’ve discovered is how well it integrates with both existing and new Rails projects. We’ve been able to completely overhaul UI on older Rails applications without retooling and we’ve found ourselves just using vanilla Rails + Stimulus vs immediately gravitating towards React, especially for relatively simple UI’s that don’t require a lot of complex state management. We’ve recently been coupling Stimulus with Turbo and are often able to deliver single-page application (SPA) level interactivity significantly faster and with fewer moving parts.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.typescriptlang.org/"&gt;Typescript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You can take Typescript out of our cold, dead hands. It has become an integral piece of React/Javascript projects and is our default lingua in the JS ecosystem. We appreciate all the work happening in the language and get excited by all the new tools that are getting released.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://nextjs.org/"&gt;NextJS&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;My outlook on NextJS is more opaque than the other stacks we use. We’ve used it on a few projects and overall had a favorable opinion of it but have yet to find its sweet spot. For purely front-end we default to &lt;a href="https://create-react-app.dev/"&gt;create-react-app&lt;/a&gt; but have had some success with Next. On full-stack/back-end it lacks all the out-of-the box utilities and conventions Rails provides resulting in a lot of external dependencies and bike-shedding on how to structure complex back-end apps. I also think Vercel (maintainer of NextJS) is missing the bus by not having a database option tightly integrated within their stack, which makes it a non-starter for us on most projects. We've found &lt;a href="http://www.digitalocean.com"&gt;DigitalOcean&lt;/a&gt; or &lt;a href="http://www.heroku.com"&gt;Heroku&lt;/a&gt; to deliver the best out-of-the-box experience when deploying full-stack NextJS apps that require server-side data persistence.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;On a personal note, I hope 2022 is the year we no longer need to use Webpack. In the Rails ecosystem, I’m quite excited about jsbundling/import-maps and the complete removal of Webpacker as a dependency. On the JS side, I hope recent advancements in build tooling with TypeScript further reduce the need and complexity of transpiling and webpacker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I don’t anticipate any bold technology projections or big changes happening at The Gnar Company in 2022. We are attracted to tools that produce quality results for our clients while still allowing us to innovate. I'm excited for the incremental improvements and enhancements we'll see within the core tech we use and will pay close attention to emerging trends in open source tech stacks.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Learn more about how The Gnar &lt;a href="https://www.thegnar.com/software-development"&gt;builds software&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
