<?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: Rafael Dias</title>
    <description>The latest articles on Forem by Rafael Dias (@theminimalistdeveloper).</description>
    <link>https://forem.com/theminimalistdeveloper</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%2F461050%2F739c5c6e-ce7a-48a1-8317-6f15a24d4e67.jpeg</url>
      <title>Forem: Rafael Dias</title>
      <link>https://forem.com/theminimalistdeveloper</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/theminimalistdeveloper"/>
    <language>en</language>
    <item>
      <title>Minimalist blog with Zola, AWS CDK, and Tailwind CSS - Part 1</title>
      <dc:creator>Rafael Dias</dc:creator>
      <pubDate>Wed, 19 Feb 2025 08:30:04 +0000</pubDate>
      <link>https://forem.com/theminimalistdeveloper/minimalist-blog-with-zola-aws-cdk-and-tailwind-css-part-1-4poh</link>
      <guid>https://forem.com/theminimalistdeveloper/minimalist-blog-with-zola-aws-cdk-and-tailwind-css-part-1-4poh</guid>
      <description>&lt;p&gt;Originally posted in &lt;a href="https://www.theminimalistdeveloper.com/minimalist-blog-with-zola-and-tailwindcss-part-1/" rel="noopener noreferrer"&gt;https://www.theminimalistdeveloper.com/minimalist-blog-with-zola-and-tailwindcss-part-1/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Assumptions, clarifications, and reasons
&lt;/h2&gt;

&lt;p&gt;What are we going to do today? We're going to build a minimalist blog using &lt;a href="https://www.getZola.org/" rel="noopener noreferrer"&gt;Zola&lt;/a&gt; (built with &lt;a href="https://rust-lang.org" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;, btw), &lt;a href="https://aws.amazon.com/cdk" rel="noopener noreferrer"&gt;AWS CDK&lt;/a&gt;, &lt;a href="https://tailwindcss.com" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;, and a tiny bit of &lt;a href="https://typescriptlang.org" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We will have a fully functional blog structure that you can pimp up as you see fit, we will not cover CI/CD pipelines, nor any automation.&lt;/p&gt;

&lt;p&gt;I can already feel some of you itching out to furiously type: Why not use &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; / Whatever other company that does the same thing / whatever instead! :angry foaming face:&lt;/p&gt;

&lt;p&gt;For a few reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I like to have control over the infrastructure of my personal websites so I can easily experiment.&lt;/li&gt;
&lt;li&gt;Familiarity with AWS and CDK.&lt;/li&gt;
&lt;li&gt;I want to.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With that out of the way, let's move on.&lt;/p&gt;

&lt;p&gt;I've used a few different engines on different personal websites, and I tend to use them as experiment grounds as much as mediums to share my thoughts.&lt;/p&gt;

&lt;p&gt;The setup I had before in this blog before was a &lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;NextJS&lt;/a&gt; / Vercel / Headless CMS combo. I hated it, way too many pieces for my use case, and didn't align with my preferred workflow.&lt;/p&gt;

&lt;p&gt;So I scraped that and started fresh with a few rules to guide the development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The content has to be stored in &lt;a href="https://www.markdownguide.org" rel="noopener noreferrer"&gt;Markdown&lt;/a&gt; - I take notes and do drafts in Markdown, so it felt like it would shorten the actions necessary to push content out if everything was Markdown.&lt;/li&gt;
&lt;li&gt;It has to be statically generated - I don't want server-side render something that will never/very unlikely to change.&lt;/li&gt;
&lt;li&gt;The tool has to be simple and robust enough with as few dependencies as possible. I want to be able to pick up and run in whatever machine in no time.&lt;/li&gt;
&lt;li&gt;The frontend setup should be simple and easy to extend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that in mind, I quickly narrowed down to a few challengers &lt;a href="https://gatsbyjs.comg" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; and &lt;a href="https://gohugo.io" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt; being the usual suspects.&lt;/p&gt;

&lt;p&gt;I've had experience with both in the past and had some gripes with both of them. After some research I came across Zola, it is a static website generator written in Rust with 0 dependencies, that works with an extended version of Markdown.&lt;/p&gt;

&lt;p&gt;Seemed too good to be true, but it isn't. A healthy community, with over 14k stars on GitHub and good enough documentation? I am in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup the project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CDK
&lt;/h3&gt;

&lt;p&gt;First, let's install AWS CDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# This will install the CDK command line tool globally&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; aws-cdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the condensed version, you can find more information in their &lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html" rel="noopener noreferrer"&gt;Getting started page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, create the blog folder, in our example it will be &lt;em&gt;my-blog&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-blog
&lt;span class="nb"&gt;cd &lt;/span&gt;my-blog
npx cdk init app &lt;span class="nt"&gt;--language&lt;/span&gt; typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above commands will create the initial setup for our infrasctucture in Typescript with a Git repository.&lt;/p&gt;

&lt;p&gt;I am assuming you have set up your AWS account and credentials, if not follow the &lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/prerequisites.html" rel="noopener noreferrer"&gt;official tutorial&lt;/a&gt; before reading any further.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zola
&lt;/h3&gt;

&lt;p&gt;Make sure you have Zola installed. They have a pretty &lt;a href="https://www.getZola.org/documentation/getting-started/installation/" rel="noopener noreferrer"&gt;extensive list of ways of installing it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, let's set up our blog. Within the &lt;em&gt;my-blog&lt;/em&gt; folder, we created in the previous step, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zola init my-blog &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we used the &lt;em&gt;-f&lt;/em&gt; flag, which means to force the creation of the blog structure within a folder that already contains files.&lt;/p&gt;

&lt;p&gt;This command will prompt a few questions, among them if you want to use &lt;a href="https://sass-lang.com" rel="noopener noreferrer"&gt;SaSS&lt;/a&gt; compilation and if you would like to have a search enabled.&lt;/p&gt;

&lt;p&gt;For the purposes of this example, we will answer no to both of them, don't worry, if you change your mind later you can update these details at any time on the config.toml is located in the root of the project folder.&lt;/p&gt;

&lt;p&gt;After, that you should have your blog folder set up and can already see it in action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zola serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accessing &lt;a href="http://127.0.0.1:1111" rel="noopener noreferrer"&gt;http://127.0.0.1:1111&lt;/a&gt; should show the standard Zola welcome page.&lt;/p&gt;

&lt;p&gt;Congratulations, you made a website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind CSS
&lt;/h3&gt;

&lt;p&gt;Tailwind is one of the fastest and cleanest ways of putting presentable websites together, of course, in my opinion.&lt;/p&gt;

&lt;p&gt;To install it, from the &lt;em&gt;my-blog&lt;/em&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;tailwindcss @tailwind/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we should have all the pieces in place so we can start to put our blog together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure
&lt;/h2&gt;

&lt;p&gt;I like to start with the infrastructure setup because it allows me to keep deploying as the project progresses.&lt;/p&gt;

&lt;p&gt;Static websites, I believe it is one of the easiest and cheapest things to have on AWS. We could simply just use an &lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;S3&lt;/a&gt; bucket and put all the output generated by Zola there and call it a day but this is neither elegant nor cost-effective.&lt;/p&gt;

&lt;p&gt;We will leverage &lt;a href="https://aws.amazon.com/cloudfront/getting-started/S3/?nc1=h_ls" rel="noopener noreferrer"&gt;CloudFront&lt;/a&gt; to enable a much faster, reliable, and cheap way to deliver our website.&lt;/p&gt;

&lt;p&gt;This setup will look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.theminimalistdeveloper.com%2Fminimalist-blog-with-zola-and-tailwindcss-part-1%2Fmy-blog-infrastructure-diagram.svg" 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%2Fwww.theminimalistdeveloper.com%2Fminimalist-blog-with-zola-and-tailwindcss-part-1%2Fmy-blog-infrastructure-diagram.svg" alt="Diagram for the infrastructure, a Cloudfront distribution pointing to a S3 bucket located in us-east-1" width="704" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  S3 Bucket
&lt;/h3&gt;

&lt;p&gt;Open your infrastructure stack definition at &lt;em&gt;./lib/my-blog-stack.ts&lt;/em&gt; and add the follow resource in the body of the constructor function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// This is where we will store all the assets generated from Zola, &lt;/span&gt;
    &lt;span class="c1"&gt;// essentially our entire website.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-blog&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="c1"&gt;// This speeds up the transfer of our files to S3&lt;/span&gt;
      &lt;span class="na"&gt;transferAcceleration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// This tells S3 to only allow access to our bucket through SSL &lt;/span&gt;
      &lt;span class="na"&gt;enforceSSL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="cm"&gt;/* 
        This tells S3 to remove all the contents of the bucket when we remove 
        the stack. This is particularly useful if you decide to have multiple 
        instances of the stack to let's say test a feature. 
        If you don't add this when you remove the stack, it will get stuck 
        because the bucket will be filled with files and the Stack will refuse 
        to continue the removal leading to manual intervention.
      */&lt;/span&gt;
      &lt;span class="na"&gt;removalPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RemovalPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DESTROY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// This is very important, we don't want anyone from the outside world to&lt;/span&gt;
      &lt;span class="c1"&gt;// be able to access our files directly&lt;/span&gt;
      &lt;span class="na"&gt;blockPublicAccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BlockPublicAccess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BLOCK_ALL&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;The next step is to grant access to CloudFront, so it can access our bucket as an origin for our website's files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloudfrontOAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OriginAccessIdentity&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyOriginAccessIdentity&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;comment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Allows CloudFront to reach the website bucket&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="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;grantRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cloudfrontOAI&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;s3origin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront_origins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;S3Origin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;originAccessIdentity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cloudfrontOAI&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 a small trick, if we just put our files there and ask CloudFront to pick them one to one as the requests arrive we will face a bunch of 404's. That is because CloudFront does not resolve paths ending in '/' to '/index.html' like Zola will create for us.&lt;/p&gt;

&lt;p&gt;A simple and clean solution is to introduce this bit of logic in CloudFront via a CloudFront function that makes this adjustment on the &lt;strong&gt;viewer request&lt;/strong&gt; event.&lt;/p&gt;

&lt;p&gt;This event happens before the request reaches CloudFront's cache, allowing us to direct the selected requests to the right files.&lt;/p&gt;

&lt;p&gt;This is the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;indexRedirector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Function&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Function&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;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FunctionCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromInline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
      function handler(event) {
          var request = event.request;
          var uri = request.uri;

          if (uri.endsWith('/')) {
            request.uri += 'index.html';
          }
          else if (!uri.includes('.')) {
            request.uri += '/index.html';
          }

          return request;
        }
      `&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FunctionRuntime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JS_2_0&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;Finally, we get to our CloudFront distribution, that will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cdn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Distribution&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-blog-cdn&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="c1"&gt;// This determines which object to look for in the root folder&lt;/span&gt;
      &lt;span class="na"&gt;defaultRootObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;minimumProtocolVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SecurityPolicyProtocol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TLS_V1_2_2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="cm"&gt;/* 
      Behaviors determine how CloudFront handles the assets. 
      In our case we will only need the default one.
      */&lt;/span&gt; 
      &lt;span class="na"&gt;defaultBehavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Origin tells CloudFront where to look for the files being requested&lt;/span&gt;
        &lt;span class="na"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s3origin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// Please, compress the files&lt;/span&gt;
        &lt;span class="na"&gt;compress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// This is very important, determins which HTTP methods we allow on &lt;/span&gt;
        &lt;span class="c1"&gt;// CloudFront, in our case only GET and HEAD methods&lt;/span&gt;
        &lt;span class="na"&gt;allowedMethods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AllowedMethods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ALLOW_GET_HEAD_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="cm"&gt;/* 
        This determines how we want CloudFront to behave with HTTP and HTTPS
        protocols. We will ask to redirect HTTP requests to HTTPS
        */&lt;/span&gt;
        &lt;span class="na"&gt;viewerProtocolPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ViewerProtocolPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REDIRECT_TO_HTTPS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// Cache both methods requests&lt;/span&gt;
        &lt;span class="na"&gt;cachedMethods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CachedMethods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CACHE_GET_HEAD_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// We use a managed cache policy called caching optimized&lt;/span&gt;
        &lt;span class="na"&gt;cachePolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CachePolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CACHING_OPTIMIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// here we add the function that will take care of adding the extra &lt;/span&gt;
        &lt;span class="c1"&gt;// index.html bit on the matching url's&lt;/span&gt;
        &lt;span class="na"&gt;functionAssociations&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="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;indexRedirector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;eventType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudfront&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FunctionEventType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VIEWER_REQUEST&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right now you could already use your stack as is, but it would be necessary a lot of manual effort, uploading files manually, cleaning up the CDN distribution, etc, etc.&lt;/p&gt;

&lt;p&gt;There is a huge quality of life improvement with just a few lines of code, the following bit will tell CDK when deploying the changes, to look for specific folders under a path, put them into the S3 bucket and also clean up the CDN cache so we can visualize the changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_s3_deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BucketDeployment&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-blog-deploy-website&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="c1"&gt;// Point to the folder where Zola will put the output of the website&lt;/span&gt;
      &lt;span class="na"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_s3_deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../public&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="c1"&gt;// Tell to which S3 bucket to upload to &lt;/span&gt;
      &lt;span class="na"&gt;destinationBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// Point to which Cloudfront distribution should be used&lt;/span&gt;
      &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// Tell which path should be cleaned when deployed&lt;/span&gt;
      &lt;span class="na"&gt;distributionPaths&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="s2"&gt;/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;Alright, now we can already start deploying.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# First build the website&lt;/span&gt;
zola build
&lt;span class="c"&gt;# Then deploy&lt;/span&gt;
cdk deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything went well you should see your Stack &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html" rel="noopener noreferrer"&gt;ARN&lt;/a&gt; at the end of the output.&lt;/p&gt;

&lt;p&gt;That is it for the first part, next, we will tackle the theme, page structure, content examples, and how everything comes together.&lt;/p&gt;

&lt;p&gt;See you in part 2!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cdk</category>
      <category>tailwindcss</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Take control of your learning journey</title>
      <dc:creator>Rafael Dias</dc:creator>
      <pubDate>Mon, 10 Feb 2025 09:34:32 +0000</pubDate>
      <link>https://forem.com/theminimalistdeveloper/take-control-of-your-learning-journey-267p</link>
      <guid>https://forem.com/theminimalistdeveloper/take-control-of-your-learning-journey-267p</guid>
      <description>&lt;p&gt;Originally published at: &lt;a href="https://www.theminimalistdeveloper.com/take-control-of-your-learning-journey/" rel="noopener noreferrer"&gt;theminimalistdeveloper.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Legacy
&lt;/h2&gt;

&lt;p&gt;Legacy is usually the last thing a software engineer wants to hear when they are evaluating to join a company, those green fields are always so much better they present you the opportunity of picking the latest and greatest tools of the season, so you can stay up-to-date and brag about on Linkedin.&lt;/p&gt;

&lt;p&gt;But the reality is that everything, everywhere, has legacy. Some are slightly less horrible than others, but believe me, everyone has it.&lt;/p&gt;

&lt;p&gt;Netflix? Yes. Even Google? Oh yes.&lt;/p&gt;

&lt;p&gt;In some instances, it is just way worse than others. There are cases where the tech is so ancient that the knowledge required to operate is not transferable to other companies or it is simply too painful to work on it. &lt;/p&gt;

&lt;p&gt;I've experienced both myself, it's not fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Harsh Truth
&lt;/h2&gt;

&lt;p&gt;If we remove the extremes, legacy is just part of the job, because whatever you do will become legacy, even earlier than you might think.&lt;/p&gt;

&lt;p&gt;The pace of the development of tools, frameworks, and languages is ever-increasing, which is good, but no company can provide you the environment to keep up with it.&lt;/p&gt;

&lt;p&gt;Companies, generally, are using technology to solve problems, and in most cases, the tech is only a detail in a much larger picture. Usually, if it works no one cares about how well-designed or how clean your code is.&lt;br&gt;
And to a certain extent that is a good thing, hyper fixating on tooling is a dangerous and often disastrous path.&lt;/p&gt;

&lt;p&gt;To strike the right balance of pros and cons when introducing new technologies is a skill honed throughout years of experience where a little bit of luck is also involved. &lt;/p&gt;

&lt;p&gt;Often times the wrong move can be costly, even fatal. That is why most companies tend to stick to their tried and true set of tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Work Never Ends
&lt;/h2&gt;

&lt;p&gt;While this can be good for the company, a certain level of skepticism can save a lot of headaches. For the software engineers on the other hand can be frustrating, or even complicate the further steps on their career.&lt;/p&gt;

&lt;p&gt;That is where side projects come into play, you control everything about it, and the focus can be whatever you want it to be, language, framework, OS, etc.&lt;/p&gt;

&lt;p&gt;It is a playground for you to test new ideas, tools, or just practice. The more tedious or repetitive your day job is, the more important it becomes.&lt;/p&gt;

&lt;p&gt;To some it might sound terrible: Just more work! I get it, in a way it is, but to stay competitive in software development you have to put in the extra hours to keep up with a rapidly changing environment. &lt;/p&gt;

&lt;p&gt;You will not have this time at your day job, the company pays you to solve problems not be up-to-date, or make you technically fulfilled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ok, now what?
&lt;/h2&gt;

&lt;p&gt;Once you decide to take on a side project, usually the first stop, and to some the last is: What to build?&lt;/p&gt;

&lt;p&gt;Fair point, I struggled with this one so much that I created a list of ways to approach it.&lt;/p&gt;

&lt;p&gt;Instead of giving a list of concrete ideas, here are some approaches that worked for me.&lt;/p&gt;

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

&lt;p&gt;What tools are in my day-to-day that I enjoy using, and I know exactly how I want them to behave?&lt;/p&gt;

&lt;p&gt;Music players, social networks, command line tools, wrappers to facilitate repetitive work, etc. &lt;/p&gt;

&lt;p&gt;Spend a day or two paying close attention to the software that you use and love then pick one to replicate completely or partially.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Scratch your own itch
&lt;/h3&gt;

&lt;p&gt;The good ol' strategy of trying to solve a need you already have.&lt;/p&gt;

&lt;p&gt;Do you love Spotify but would prefer to control it via Neovim? Good one.&lt;/p&gt;

&lt;p&gt;How about a nicer way to navigate your PRs? Great.&lt;/p&gt;

&lt;p&gt;A good exercise in this case is to keep pen and paper at hand and every time you miss a feature or product, describe roughly what you want. &lt;br&gt;
Do that for a week, and you will probably be surprised by the amount of things you will come up with.&lt;/p&gt;

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

&lt;p&gt;If the above approaches left you empty handed you can do the analytical way. Pick the technologies you want to learn and research for trends that you can apply.&lt;/p&gt;

&lt;p&gt;An awesome tool to play around and figure out trends is Google Trends.&lt;/p&gt;

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

&lt;p&gt;Companies will not, and cannot keep up with the release of every new cool piece of tech out there, it's not what they are there for.&lt;/p&gt;

&lt;p&gt;Despite what some might think, software development requires a lot of energy both in and out of work. But having a side project you enjoy, and have at hand to try out things and experiment might be the difference for getting your next job or even the next step in your current one.&lt;/p&gt;

&lt;p&gt;That's why I strongly advocate for side projects, there are huge benefits when you invest those extra hours. &lt;/p&gt;

&lt;p&gt;It can make you more fullfilled, sometimes happier, but &lt;strong&gt;always&lt;/strong&gt; better at your craft.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>learning</category>
      <category>sideprojects</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Everybody Wants To Get Rid Of Software Developers?</title>
      <dc:creator>Rafael Dias</dc:creator>
      <pubDate>Mon, 10 Feb 2025 09:29:58 +0000</pubDate>
      <link>https://forem.com/theminimalistdeveloper/why-everybody-wants-to-get-rid-of-software-developers-4nk9</link>
      <guid>https://forem.com/theminimalistdeveloper/why-everybody-wants-to-get-rid-of-software-developers-4nk9</guid>
      <description>&lt;p&gt;Originally published at: &lt;a href="https://www.theminimalistdeveloper.com/why-everybody-wants-to-get-rid-of-sotware-developers/" rel="noopener noreferrer"&gt;theminimalistdeveloper.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason might be simply because they are expensive. But, as usual, I believe there is more to it.&lt;/p&gt;

&lt;p&gt;Ever since I started programming, almost 20 years ago, there is this idea that a tool, or method can completely, or at least partially, replace a skilled developer. At first, it was the visual tools like the defunct Dreamweaver, from the family of the WYSIWYG (what you see is what you get) tools.&lt;/p&gt;

&lt;p&gt;Quickly, it became clear that it was not as simple as allowing people to paint tables with a mouse would be enough. As the years went by, the applications only got more complex, and with it the wish to allow people to build them without developers.&lt;/p&gt;

&lt;p&gt;Initially, I thought it was purely financially motivated. If you can make it simpler and/or faster, it will be cheaper, but I believe there is more to it. &lt;/p&gt;

&lt;p&gt;Due to the nature of what we do, we usually work detached from the other departments of the company, mostly because it is an area that requires a lot of context from many concepts and tools to understand it. That is one of the main “hidden” points that makes the engineering role so important to be replaced by AI.&lt;/p&gt;

&lt;p&gt;Often, the word of an engineering team is the showstopper of executives, creatives, and product people wet dream. Your idea might be fantastic, but if the engineering team deems it not feasible, or if it takes too long to implement, it might be in some way or another dead in the water.&lt;/p&gt;

&lt;p&gt;And you add to that the lack of room for counterarguments because they are in most ways too hermetic and require deep technical knowledge to effectively navigate the discussion.&lt;/p&gt;

&lt;p&gt;That can be a much more compelling reason than the financial, the general lack of trust and the feeling of powerlessness over the product have a massive negative effect on many companies.&lt;/p&gt;

&lt;p&gt;Now imagine if those developers that always deny your requests, and in your opinion, take too long to complete their tasks, could be replaced by some magical tool, wouldn't that be amazing? &lt;/p&gt;

&lt;p&gt;All the world-disrupting ideas for your app could be transmitted straight from your mind to the real world through simple prompts!&lt;/p&gt;

&lt;p&gt;Your genius would shine without being obfuscated by lazy, awkward, slow, and overpaid developers.&lt;/p&gt;

&lt;p&gt;Such a great idea, but unfortunately, reality is not as simple as that. The first issue that real-world ideas can't be directly translated to software without considering contextual, technical, and non-technical aspects that directly impact a system's design.&lt;/p&gt;

&lt;p&gt;Company dynamics, other internal and external systems, physical limitations, the list goes on and on, that even the most accurate LLM cannot even scratch the surface.&lt;/p&gt;

&lt;p&gt;A huge portion of engineering work is to disambiguate murky feature requirements, translate wishes into tangible actions, spot patterns in the human dynamics of the team and the company.&lt;/p&gt;

&lt;p&gt;That is nowhere near the wheelhouse of the tools that flood the market today, claiming to be software engineering replacements.&lt;/p&gt;

&lt;p&gt;See, I am not even getting into the quality of the output of those tools, which arguably, aren't particularly good to begin with.&lt;/p&gt;

&lt;p&gt;Now, with that said, I have to also be honest, there is a general lack of soft skills ingrained in parts of our software engineering community.&lt;br&gt;
Either it is a trait that naturally develops due to the environment, or is the profile of the professional that gets attracted by the field, I don't know.&lt;/p&gt;

&lt;p&gt;It is not unusual to see unresponsive, incommunicable developers that just want to close tickets. Soft skills, and most importantly communication, are the hidden gold of the AI era that we are in.&lt;/p&gt;

&lt;p&gt;You need to be good technically, that is not negotiable. Specialize yourself, but also be an effective communicator and nice team member.&lt;/p&gt;

&lt;p&gt;That's why it is the first thing I probe for whenever I am hiring for our teams.&lt;/p&gt;

&lt;p&gt;Any reasonably good engineer should be able to pick up a new language and be productive relatively quickly. On the other hand, it's hard, costly and sometimes even impossible to teach someone on how to effectively clarify complex abstract ideas from non-technical people, for example.&lt;/p&gt;

&lt;p&gt;AI tools are amazing, they can help you be more productive, speed up tedious tasks, but we are still far off from being able to create something that can navigate the unbelievably complex network of human interactions. &lt;/p&gt;

&lt;p&gt;And my friends, that is a good thing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Re:Invent 2020 And Lambda's New Features</title>
      <dc:creator>Rafael Dias</dc:creator>
      <pubDate>Sun, 29 Nov 2020 12:30:00 +0000</pubDate>
      <link>https://forem.com/theminimalistdeveloper/re-invent-2020-and-lambda-s-new-features-42c9</link>
      <guid>https://forem.com/theminimalistdeveloper/re-invent-2020-and-lambda-s-new-features-42c9</guid>
      <description>&lt;p&gt;Originally posted on &lt;a href="https://www.theminimalistdeveloper.com/reinvet-2020-and-lambdas-new-features/" rel="noopener noreferrer"&gt;The Minimalist Developer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="/static/72c18026489cf607f5ea267ff3765af8/7bf07/post-image.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.theminimalistdeveloper.com%2Fstatic%2F72c18026489cf607f5ea267ff3765af8%2F59822%2Fpost-image.png" title="Cute little robot" alt="Cute little robot" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reinvent.awsevents.com/" rel="noopener noreferrer"&gt;Re:Invent 2020&lt;/a&gt; is approaching, and with it, a wave of new releases from AWS to multiple services, including Lambda.&lt;/p&gt;

&lt;p&gt;This year, of course, will be an online-only event which is free. Go &lt;a href="https://serverlessland.com/reinvent2020" rel="noopener noreferrer"&gt;here&lt;/a&gt; to check out all the serverless sessions.&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at some of the coolest releases from the past few weeks for Lambda we will probably see covered in the upcoming events.&lt;/p&gt;

&lt;h2&gt;
  
  
  New Lambda Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lambda extensions
&lt;/h3&gt;

&lt;p&gt;&lt;a href="/static/aa951ce6695ea93bfb6d43d9a0380e92/2bef9/lambda-extensions.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.theminimalistdeveloper.com%2Fstatic%2Faa951ce6695ea93bfb6d43d9a0380e92%2F59822%2Flambda-extensions.png" title="Lambda extensions" alt="Lambda extensions" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is still in preview, but this is probably the most exciting release, in my opinion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/blogs/compute/building-extensions-for-aws-lambda-in-preview/" rel="noopener noreferrer"&gt;Lambda extension&lt;/a&gt; allows us to have code running during the life cycle event, meaning that you could, for example, create an extension to collect information before, during, and after the lambda invocation.&lt;/p&gt;

&lt;p&gt;Also, there is a Logs API, which translates to much easier integration with 3rd party services like Datadog, Lumigo, New Relic, etc.&lt;/p&gt;

&lt;p&gt;This sounds &lt;strong&gt;really&lt;/strong&gt; nice. I want to try it out to see how it works!&lt;/p&gt;

&lt;h3&gt;
  
  
  AVX2 Support
&lt;/h3&gt;

&lt;p&gt;&lt;a href="/static/d94ab35cb480fa909532437b5c132a5f/82e86/avx21.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.theminimalistdeveloper.com%2Fstatic%2Fd94ab35cb480fa909532437b5c132a5f%2F59822%2Favx21.png" title="AVX2" alt="AVX2" width="800" height="400"&gt;&lt;/a&gt;This one is geared towards those who use lambdas for heavy computational load, like machine learning, scientific simulations, financial analysis, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/blogs/compute/creating-faster-aws-lambda-functions-with-avx2" rel="noopener noreferrer"&gt;AVX2 support&lt;/a&gt; is availabel now to help reduce time with the computationally intensive task that way also helping to reduce costs.&lt;/p&gt;

&lt;p&gt;AVX2 stands for Advanced Vector Extensions 2, and it is a specific instruction set available at certain processors. And to use it it is necessary to have in place certain libraries compiled with the proper flags.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS PrivateLink access
&lt;/h3&gt;

&lt;p&gt;Lambda now offers the support for &lt;a href="https://aws.amazon.com/privatelink" rel="noopener noreferrer"&gt;AWS PrivateLink&lt;/a&gt;. It allows calling functions from a VPC without going through public networks. Providing a private connection between your VPCs and AWS services.&lt;/p&gt;

&lt;p&gt;I want to see how the performance is with this one. The last time I checked VPCs and Lambdas were not that great together. But it was a long time ago.&lt;/p&gt;

&lt;h3&gt;
  
  
  SQS batch Limit up to 10k
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/sqs/" rel="noopener noreferrer"&gt;Amazon SQS&lt;/a&gt; had previously, the batch size limit of 10 messages per batch. Now it is up to 10.000, matching its brother Amazon Kinesis.&lt;/p&gt;

&lt;h3&gt;
  
  
  SQS Batch Window up to 5 minutes
&lt;/h3&gt;

&lt;p&gt;The Batch window is a cool little feature. It tells the poller to wait until the queue has reached its batch limit or the batch window time to send to the lambda function. This is particularly useful to cut the number of invocations for non-time-sensitive computation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Amazon MQ as an event source
&lt;/h3&gt;

&lt;p&gt;Launched support for &lt;a href="https://aws.amazon.com/amazon-mq" rel="noopener noreferrer"&gt;Amazon MQ&lt;/a&gt; as an event source for Lambda. Amazon MQ is a managed message broker service. The integration operates in a similar way to Amazon SQS and Amazon Kinesis. The Lambda services keep an internal poller to invoke the target Lambda function whenever necessary.&lt;/p&gt;

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

&lt;p&gt;There are many more features from other services that AWS is launching. Make sure to keep an eye on the releases.&lt;/p&gt;

&lt;p&gt;It might help you solve one of those pending problems from your backlog!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>sqs</category>
      <category>news</category>
    </item>
    <item>
      <title>Setting Up Typescript Project From Scratch</title>
      <dc:creator>Rafael Dias</dc:creator>
      <pubDate>Sun, 29 Nov 2020 10:25:00 +0000</pubDate>
      <link>https://forem.com/theminimalistdeveloper/setting-up-typescript-project-from-scratch-3ho9</link>
      <guid>https://forem.com/theminimalistdeveloper/setting-up-typescript-project-from-scratch-3ho9</guid>
      <description>&lt;p&gt;Originally posted on &lt;a href="https://www.theminimalistdeveloper.com/setting-up-typescript-project-from-scratch/" rel="noopener noreferrer"&gt;The Minimalist Developer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="/static/b05094a690cb6d46289f21b263d47a0d/11a8f/post-image.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.theminimalistdeveloper.com%2Fstatic%2Fb05094a690cb6d46289f21b263d47a0d%2F59822%2Fpost-image.png" title="Start building" alt="Start building" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;You don’t want to read through all those steps? Dive in straight into coding, just clone/download/fork &lt;a href="https://github.com/theminimalistdeveloper/base-typescript-project" rel="noopener noreferrer"&gt;this repository&lt;/a&gt; with the resulting base project of this post 😀.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Whenever learning a new language after &lt;a href="https://dev.to/theminimalistdeveloper/setting-up-neovim-for-typescript-development-57dl"&gt;configuring a proper development environment&lt;/a&gt;, set up a project from scratch is the next step on my list.&lt;/p&gt;

&lt;p&gt;To understand how to have everything in the right place to start coding is essential. Of course, after the first few times, you will probably automate these steps or would rely on some boilerplate project.&lt;/p&gt;

&lt;p&gt;The idea of this post is to walk through the very first steps necessary to have a project correctly set up for Typescript, and by correctly, I mean having these things in place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project structure&lt;/strong&gt; : Folder structure, Git, NPM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unit test setup&lt;/strong&gt; : Jest&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Style guide&lt;/strong&gt; : Airbnb style guide for Typescript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPM Scripts&lt;/strong&gt; : Wrap up common commands in NPM scripts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre commit hooks&lt;/strong&gt; : To ensure we don’t tarnish our immaculate repository&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure could be used for front-end development, probably with some tweaks here and there. But for my purpose and also for the post, it is oriented for backend development.&lt;/p&gt;

&lt;p&gt;Also, everything here is aimed towards &lt;strong&gt;*nix&lt;/strong&gt; environments, either be some Linux flavor or MacOs, with &lt;strong&gt;NodeJS&lt;/strong&gt; and &lt;strong&gt;Git&lt;/strong&gt; installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1 - Initiate the Project
&lt;/h3&gt;

&lt;p&gt;Define the folder name that will house our project. In this case, let’s call it &lt;strong&gt;ts-project&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ts-project/&lt;span class="o"&gt;{&lt;/span&gt;src,tests/unit/src&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will generate this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts-project
├── src
└── tests
    └── unit
        └── src

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hop into the project’s folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;ts-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initiate an empty Git Repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a &lt;strong&gt;.gitignore&lt;/strong&gt; file at the root of the project with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules/
dist/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which will tell Git to not track the changes on those folders.&lt;/p&gt;

&lt;p&gt;Initiate an NPM project. The &lt;strong&gt;-y&lt;/strong&gt; tells NPM to accept all the default settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Typescript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not ignore the —save-dev flag. It tells NPM to add the Typescript package to the dev dependency list on our newly added &lt;strong&gt;package.json&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Initiate Typescript by issuing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx tsc &lt;span class="nt"&gt;--init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line deserves a word or two. Alongside NPM, it is installed another tool called &lt;a href="https://www.npmjs.com/package/npx" rel="noopener noreferrer"&gt;NPX&lt;/a&gt;. NPX is a tool to execute binaries without having them installed globally. It will look for the executable first at the environment variable $PATH, then in the local project for the requested command, in this case, tsc.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;tsc&lt;/strong&gt; portion of the command refers to the Typescript dependency. When executed, the above command should display something like this as a result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message TS6071: Successfully created a tsconfig.json file.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It creates a configuration file called &lt;strong&gt;tsconfig.json&lt;/strong&gt; with parameters necessary for Typescript to work properly.&lt;/p&gt;

&lt;p&gt;By default, all possible configuration keys are present, but most of them, will be commented out. After cleaning up the unnecessary commented lines you will be left with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a detailed description of what each of these fields means, please check the official documentation right &lt;a href="https://www.typescriptlang.org/tsconfig" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s tweak this a little bit. Add two new keys to the compiler options&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"sourceMap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;outDir&lt;/strong&gt; : being the destination folder of the transpiled code will be stored, in this case, we go with the most common of all, dist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sourceMap&lt;/strong&gt; : enables the generation of source map files. They allow debuggers and other tools to show the original Typescript when debugging the compiled Javascript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And at the root we add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./src/**/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which tells the compiler to take everything from the source (src) folder.&lt;/p&gt;

&lt;p&gt;The end result is something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./src/**/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2 - Unit Tests
&lt;/h3&gt;

&lt;p&gt;For unit tests, I have been using &lt;a href="https://jestjs.io/en/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; for quite some time now, no complaints.&lt;/p&gt;

&lt;p&gt;Very straight forward and simple testing framework.&lt;/p&gt;

&lt;p&gt;To install all the packages necessary run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  jest &lt;span class="se"&gt;\&lt;/span&gt;
  babel-jest &lt;span class="se"&gt;\&lt;/span&gt;
  @babel/core &lt;span class="se"&gt;\&lt;/span&gt;
  @babel/preset-env &lt;span class="se"&gt;\&lt;/span&gt;
  @babel/preset-typescript &lt;span class="se"&gt;\&lt;/span&gt;
  @types/jest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add a &lt;strong&gt;babe.config.js&lt;/strong&gt; at the root of the project with the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;module.exports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;presets:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'@babel/preset-env'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;targets:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;node:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'current'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;'@babel/preset-typescript'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our testing setup is done.&lt;/p&gt;

&lt;h3&gt;
  
  
  3 - Style guide and linting
&lt;/h3&gt;

&lt;p&gt;This is a crucial step to ensure, among other things consistency. I am have been working with the &lt;a href="https://github.com/airbnb/javascript" rel="noopener noreferrer"&gt;Airbnb style guide for Javascript&lt;/a&gt; for almost two years, and love it. Helps to fix smaller mistakes literally pointing out to you.&lt;/p&gt;

&lt;p&gt;To be able to use the same ruleset on Typescript, we are going to use a package called &lt;a href="https://www.npmjs.com/package/eslint-config-airbnb-typescript" rel="noopener noreferrer"&gt;eslint-config-airbnb-typescript&lt;/a&gt;, which is a drop-in replacement for the normal &lt;strong&gt;eslint-config-airbnb&lt;/strong&gt; but with all the Typescript goodness.&lt;/p&gt;

&lt;p&gt;To install, run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    eslint &lt;span class="se"&gt;\&lt;/span&gt;
    eslint-config-airbnb-typescript &lt;span class="se"&gt;\&lt;/span&gt;
    eslint-plugin-import@^2.22.0 &lt;span class="se"&gt;\&lt;/span&gt;
    @typescript-eslint/eslint-plugin@^4.4.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add &lt;strong&gt;.eslintrc.js&lt;/strong&gt; to the project root with the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;module.exports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;extends:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'airbnb-typescript/base'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;parserOptions:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;project:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'./tsconfig.json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case you went through my last post ”&lt;a href="https://dev.to/theminimalistdeveloper/setting-up-neovim-for-typescript-development-57dl"&gt;Setting up Neovim for typescript development&lt;/a&gt;” you will notice that this style guide uses Eslint, and we configured the only tsserver. To add Coc support for Eslint run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;CocInstall coc&lt;span class="p"&gt;-&lt;/span&gt;eslint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out its &lt;a href="https://github.com/neoclide/coc-eslint" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to learn more about the extension.&lt;/p&gt;

&lt;h3&gt;
  
  
  4 - NPM Scripts
&lt;/h3&gt;

&lt;p&gt;Let’s leverage the &lt;a href="https://docs.npmjs.com/cli/v6/using-npm/scripts" rel="noopener noreferrer"&gt;NPM scripts&lt;/a&gt; system to facilitate interacting with the tooling we just set up.&lt;/p&gt;

&lt;p&gt;This seems like a trivial, maybe unnecessary step, but having the tooling abstracted by the scripts can help to decouple it from other parts like some editor shortcuts or CI/CD pipelines. So in case, you decide to change your testing library or build process, we can simply change it in one place.&lt;/p&gt;

&lt;p&gt;Add this piece of code at the root of the package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"compile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are pretty self-explanatory, but here are examples of how we can use these scripts. From the project root run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# This will run the testing library Jest&lt;/span&gt;
npm run &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="c"&gt;# This will run the linting&lt;/span&gt;
npm run lint
&lt;span class="c"&gt;# This will run the compilation&lt;/span&gt;
npm run compile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5 - Pre-Commit Hooks
&lt;/h3&gt;

&lt;p&gt;Finishing up with some fail-safes, it can make our lifes much easier. &lt;a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks" rel="noopener noreferrer"&gt;Git hook&lt;/a&gt; is a neat feature from Git, it allows us to run scripts in certain key events like before applying a commit, before pushing, and many others.&lt;/p&gt;

&lt;p&gt;In this example, we will use a package called &lt;a href="https://www.npmjs.com/package/pre-commit" rel="noopener noreferrer"&gt;pre-commit&lt;/a&gt; to run our scripts before the commits. To install it, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; pre-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then add this to package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"pre-commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"compile"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will make sure that every time you issue a commit command, runs all the three npm scripts. That way, we will never be able to event commit broken or invalid code.&lt;/p&gt;

&lt;h3&gt;
  
  
  6 - Testing
&lt;/h3&gt;

&lt;p&gt;With everything in place, let’s write a “hello world” and test it. Add an &lt;strong&gt;index.ts&lt;/strong&gt; to your &lt;strong&gt;src&lt;/strong&gt; folder, located at the root of the project with this content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Hello world function
 *
 * @param {string} name
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;helloWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="s2"&gt;`Hello world, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;helloWorld&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add an &lt;strong&gt;index.spec.ts&lt;/strong&gt; at &lt;strong&gt;tests/unit/src&lt;/strong&gt; with this content;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;helloWorld&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;../../../src/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world works&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;helloWorld&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Foo&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="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world, Foo&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, from the command line at the root of the project, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run lint &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run compile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which should result in something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ts-project@1.0.0 lint /Users/username/ts-project
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; eslint

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ts-project@1.0.0 &lt;span class="nb"&gt;test&lt;/span&gt; /Users/username/ts-project
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; jest

 PASS tests/unit/src/index.spec.ts
  ✓ Hello world works &lt;span class="o"&gt;(&lt;/span&gt;2 ms&lt;span class="o"&gt;)&lt;/span&gt;

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.898 s, estimated 1 s
Ran all &lt;span class="nb"&gt;test &lt;/span&gt;suites.

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ts-project@1.0.0 compile /Users/username/ts-project
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; tsc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve made it!&lt;/p&gt;

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

&lt;p&gt;These kinds of steps are valuable to understand all the moving parts that compose a base project structure, but after a couple of times, these steps should be automated or a boilerplate that fits your needs created.&lt;/p&gt;

&lt;p&gt;We went through all the steps to set up a solid foundation for our experiments and projects. Now the only thing left is to build something cool.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Setting Up Neovim For Typescript Development</title>
      <dc:creator>Rafael Dias</dc:creator>
      <pubDate>Mon, 23 Nov 2020 19:00:00 +0000</pubDate>
      <link>https://forem.com/theminimalistdeveloper/setting-up-neovim-for-typescript-development-57dl</link>
      <guid>https://forem.com/theminimalistdeveloper/setting-up-neovim-for-typescript-development-57dl</guid>
      <description>&lt;p&gt;&lt;a href="/static/86c8e4537055394dbbebc1149b2d4c6e/87488/post-image.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.theminimalistdeveloper.com%2Fstatic%2F86c8e4537055394dbbebc1149b2d4c6e%2F59822%2Fpost-image.png" title="Hacking away" alt="Hacking away" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally posted on &lt;a href="https://www.theminimalistdeveloper.com/setting-up-neovim-for-typescript-development/" rel="noopener noreferrer"&gt;theminimalistdeveloper.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;First things first, right? Yes. So, I am learning &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; whenever I start learning a new programming language, I begin by setting up a development environment.&lt;/p&gt;

&lt;p&gt;Everything necessary to properly run the code snippets, tests, etc. It feels like a solid foundation to start building on.&lt;/p&gt;

&lt;p&gt;Since my weapon of choice is &lt;a href="https://neovim.io/" rel="noopener noreferrer"&gt;Neovim&lt;/a&gt;, here I will describe what it took for me to have a development environment for Typescript with autocomplete, jump to definition, code validation, documentation display in place, and all that good stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;This post will focus specifically on the components necessary for Typescript development. I am assuming you already have Neovim installed and configured. If that is not your case, don't panic! Check out &lt;a href="https://rafaelnexus.com/tutorials/what-is-neovim-and-how-to-install-it-with-python-support/" rel="noopener noreferrer"&gt;this&lt;/a&gt; short and straight to the point post on what is Neovim and how to install it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Git
&lt;/h3&gt;

&lt;p&gt;🔗 &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;git-scm.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Coc and its extensions require Git. It is fair to assume that every developer has Git on their machines, but better safe than sorry :D&lt;/p&gt;

&lt;h3&gt;
  
  
  NodeJS
&lt;/h3&gt;

&lt;p&gt;🔗 &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;nodejs.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to, you know, run the code after compiling it. I currently am using version 12.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plug
&lt;/h3&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/junegunn/vim-plug" rel="noopener noreferrer"&gt;github.com/junegunn/vim-plug&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Plug is a plugin manager for Vim/Neovim. It is possible to achieve the same result with any other plugin manager for Vim or Neovim, but if you want to follow along with this post, it is easier to have Plug in place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CoC
&lt;/h3&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/neoclide/coc.nvim" rel="noopener noreferrer"&gt;github.com/neoclide/coc.nvim&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CoC or Conquer of Completion is a plugin that interfaces with language servers to provides a lot of great features like proper autocomplete, jump to definition, documentation display, refactoring tools, etc.&lt;/p&gt;

&lt;p&gt;The installation of the CoC is very straight forward. Simply add this line to your init file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plug 'neoclide/coc.nvim', {'branch': 'release'}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run on Neovim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:PlugInstall
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is the command from Plug to install the plugins listed on your init file. Remember to source again your init file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source /path/to/your/init.vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CoC Tsserver extension
&lt;/h3&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/neoclide/coc-tsserver" rel="noopener noreferrer"&gt;github.com/neoclide/coc-tsserver&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CoC plugin on its own does not do much for us. We need to install an extension to add the features we want.&lt;/p&gt;

&lt;p&gt;The extension in question is called Tsserver, which is a language server for Typescript and Javascript.&lt;/p&gt;

&lt;p&gt;To install, run this command from Neovim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:CocInstall coc-tsserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To check if everything went as expected, run this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:CocList extensions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will open up a window with all the installed extensions for CoC, you should see listed, something 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;+ coc-tsserver 1.5.6 ~/.config/coc/extensions/node_modules/coc-tsserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means that everything is correct!&lt;/p&gt;

&lt;p&gt;So, what can we expect from this extension?&lt;br&gt;
Here is the feature list from the official Github repository:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Supports javascript &amp;amp; typescript and jsx/tsx.&lt;/p&gt;

&lt;p&gt;Installs typings automatically.&lt;/p&gt;

&lt;p&gt;Commands to work with tsserver, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;tsserver.reloadProjects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tsserver.openTsServerLog&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tsserver.goToProjectConfig&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tsserver.restart&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tsserver.organizeImports&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tsserver.watchBuild&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code completion support.&lt;/p&gt;

&lt;p&gt;Go to definition.&lt;/p&gt;

&lt;p&gt;Code validation.&lt;/p&gt;

&lt;p&gt;Document highlight.&lt;/p&gt;

&lt;p&gt;Document symbols of current buffer.&lt;/p&gt;

&lt;p&gt;Folding and folding range of current buffer.&lt;/p&gt;

&lt;p&gt;Format current buffer, range format, and format on type.&lt;/p&gt;

&lt;p&gt;Hover for documentation.&lt;/p&gt;

&lt;p&gt;Implementations codeLens and references codeLens.&lt;/p&gt;

&lt;p&gt;Organize imports command.&lt;/p&gt;

&lt;p&gt;Quickfix using code actions.&lt;/p&gt;

&lt;p&gt;Code refactor using code actions.&lt;/p&gt;

&lt;p&gt;Find references.&lt;/p&gt;

&lt;p&gt;Signature help.&lt;/p&gt;

&lt;p&gt;Rename symbols support.&lt;/p&gt;

&lt;p&gt;Rename imports on file rename, require watchman installed in your $PATH.&lt;/p&gt;

&lt;p&gt;Search for workspace symbols.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A pretty sweet list, huh?&lt;/p&gt;

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

&lt;p&gt;As we've seen, it is not that difficult to have a complete Typescript setup running with Neovim and CoC in no time.&lt;br&gt;
There is so much more we can tweak and improve. This is the bare minimum to get you going with Typescript on Neovim.&lt;/p&gt;

&lt;p&gt;Next, let's dig a little deeper on Tsserver CoC extension and some other cool Neovim plugins!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>neovim</category>
      <category>vim</category>
      <category>node</category>
    </item>
    <item>
      <title>Home Development Setup 2020 - Pandemic Edition</title>
      <dc:creator>Rafael Dias</dc:creator>
      <pubDate>Mon, 10 Aug 2020 07:00:00 +0000</pubDate>
      <link>https://forem.com/theminimalistdeveloper/home-development-setup-2020-pandemic-edition-5eof</link>
      <guid>https://forem.com/theminimalistdeveloper/home-development-setup-2020-pandemic-edition-5eof</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.theminimalistdeveloper.com%2Fstatic%2Fdd697ad64abbf9347f729d0a7453d52f%2F59822%2Fpost-image.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%2Fwww.theminimalistdeveloper.com%2Fstatic%2Fdd697ad64abbf9347f729d0a7453d52f%2F59822%2Fpost-image.png" title="Futuristic work station" alt="Futuristic work station" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ah, 2020, what a year! &lt;a href="https://en.wikipedia.org/wiki/COVID-19_pandemic" rel="noopener noreferrer"&gt;Raging Covid-19 pandemic&lt;/a&gt;, &lt;a href="https://www.nationalgeographic.com/animals/2020/05/asian-giant-hornets-arrive-united-states/" rel="noopener noreferrer"&gt;killer wasps&lt;/a&gt;, &lt;a href="https://www.theguardian.com/world/2019/jul/03/jair-bolsonaro-brazil-first-six-months-right-dismayed" rel="noopener noreferrer"&gt;Bolsonaro&lt;/a&gt;, &lt;a href="https://www.theguardian.com/world/2020/aug/07/german-nudist-chases-wild-boar-that-stole-laptop-berlin-teufelssee" rel="noopener noreferrer"&gt;a family of wild boars stealing notebooks from naked middle-aged men&lt;/a&gt;, &lt;a href="https://www.bbc.com/news/world-asia-china-53325988" rel="noopener noreferrer"&gt;bubonic plague&lt;/a&gt;, whatever your wildest nightmares can request, 2020 can deliver.&lt;/p&gt;

&lt;p&gt;Amid such challenging times, we have been, most of us forcedly, working from home for the past five months or so, so a good home-office setup is more relevant than ever!&lt;/p&gt;

&lt;p&gt;It comes as no surprise to anyone that your workstation and equipment can impact drastically, not just your productivity but your overall well being. Our work environment is sometimes where we spent the bulk of our days, so every detail counts.&lt;/p&gt;

&lt;p&gt;Luckily for us at home, me and my wife, we have been improving and experimenting with the home office way before the lockdown started, so when the pandemic struck, we were all set.&lt;/p&gt;

&lt;p&gt;We designed the space for the two of us, but I will focus in this post on my workstation, which is focused mainly on development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.theminimalistdeveloper.com%2Fstatic%2F06589d1f47ae701042a0dd15a3187484%2Ff212f%2Fworkstation-front-view.jpg" 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%2Fwww.theminimalistdeveloper.com%2Fstatic%2F06589d1f47ae701042a0dd15a3187484%2Ff212f%2Fworkstation-front-view.jpg" title="Workstation front view" alt="Workstation front view" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Desk
&lt;/h2&gt;

&lt;p&gt;Everything starts with the desk. It’s the foundation of the workspace.&lt;/p&gt;

&lt;p&gt;First, I was looking for two distinct desks, ended up leaning towards a big tabletop one able to support two workspaces. It felt cleaner and more uniform.&lt;/p&gt;

&lt;p&gt;I chose a kitchen tabletop from Ikea called &lt;a href="https://www.ikea.com/de/de/p/karlby-arbeitsplatte-nussbaum-furnier-00335201/?gclsrc=aw.ds&amp;amp;&amp;amp;gclid=Cj0KCQjwp4j6BRCRARIsAGq4yMHkc4JDwWY7jsKfalllCGMTYE89g20YfpkTQUdA9hyBpxRb2HLdpJAaAiAYEALw_wcB" rel="noopener noreferrer"&gt;KARLBY&lt;/a&gt;. It was almost the exact size of the wall the station is on, not as wide as I hoped for, but it was relatively cheap, and it is gorgeous.&lt;/p&gt;

&lt;p&gt;As feet, I repurposed the ones from an old table that now lives on the basement storage, added an &lt;a href="https://www.ikea.com/de/de/p/alex-schubladenelement-schwarzbraun-40342285/" rel="noopener noreferrer"&gt;ALEX drawer&lt;/a&gt; (also from Ikea) in the middle, and voilá: We had a desk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.theminimalistdeveloper.com%2Fstatic%2F46217ce6a968d180546324da6ca34256%2Ff212f%2Fworkstation-side-view.jpg" 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%2Fwww.theminimalistdeveloper.com%2Fstatic%2F46217ce6a968d180546324da6ca34256%2Ff212f%2Fworkstation-side-view.jpg" title="Workstation side view" alt="Workstation side view" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Computers
&lt;/h2&gt;

&lt;p&gt;Currently, I have two computers in use. There is also an ancient Macbook Pro 13” from 2012, which I am planning to repurpose as a Linux machine for development. But that’s a topic for another post.&lt;/p&gt;

&lt;p&gt;The main machine is a Macbook Pro 15” 2019 A.K.A the work-machine, it is not mine actually, the company provided for me. It sits most of the time on a &lt;a href="https://www.twelvesouth.com/products/bookarc-macbook?variant=31443535724601" rel="noopener noreferrer"&gt;BookArc&lt;/a&gt; alluminum support from Twelve south.&lt;/p&gt;

&lt;p&gt;My personal computer at the moment is an AMD desktop (Windows/Manjaro dual boot) that I’ve built end of last year, A.K.A Doom Eternal machine because that’s all I have been doing on that computer since March.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitors
&lt;/h2&gt;

&lt;p&gt;By far, the most tried and tested aspect of my setup. I tried a lot of combinations, dispositions, and models.&lt;/p&gt;

&lt;p&gt;Dual monitor, triple monitor, dual monitor + iPad, dual monitor + laptop + iPad, ultrawide monitor, you name it. Curious about all the variations? Check out my Instagram at &lt;a href="https://instagram.com/the.minimalist.developer" rel="noopener noreferrer"&gt;@the.minimalist.developer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now I am back to the basics, 90% of the time using only a single &lt;a href="https://www.samsung.com/uk/monitors/uhd-ue570/" rel="noopener noreferrer"&gt;4k 28” Samsung U28E590&lt;/a&gt; hooked to a monitor arm I’ve found on Amazon.&lt;/p&gt;

&lt;p&gt;Depending on the tasks at hand, I might feel more comfortable with two screens, when this happens I open up the laptop and I am good to go.&lt;/p&gt;

&lt;p&gt;When working on the desktop, I rarely, if ever, feel the need for an extra monitor because of the &lt;a href="https://i3wm.org/" rel="noopener noreferrer"&gt;I3 desktop manager&lt;/a&gt;. It allows me to organize the workspace much better, with a 28” display, there is not much need for more space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keyboard
&lt;/h2&gt;

&lt;p&gt;Yep, I am the despiteful coworker that uses those typewriter-like sounding keyboards. What can I do? It feels so good!&lt;/p&gt;

&lt;p&gt;We type all day long, better be typing on something enjoyable, right? On top of the feeling, there is also an ergonomic benefit.&lt;/p&gt;

&lt;p&gt;Currently, I am using an &lt;a href="http://en.obins.net/" rel="noopener noreferrer"&gt;Anne Pro 2&lt;/a&gt; (Gateron blues switches) with the notebook and a &lt;a href="http://www.vortexgear.tw/vortex2_2.asp?kind=47&amp;amp;kind2=220&amp;amp;kind3=&amp;amp;kind4=1023" rel="noopener noreferrer"&gt;Pok3r&lt;/a&gt; (MX Clear switches) on the desktop.&lt;/p&gt;

&lt;p&gt;Usually, only one would be at home, and the other would be at the office, but since all this pandemic, I brought all my stuff from the office back home.&lt;/p&gt;

&lt;p&gt;But to be honest, none of those are the endgame for me. I will be building a new one soon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mouse
&lt;/h2&gt;

&lt;p&gt;Neglected and often forgotten, the mouse is only a central piece when I am playing, that’s when I use a &lt;a href="https://www.logitechg.com/en-us/products/gaming-mice/g305-lightspeed-wireless-gaming-mouse.910-005280.html" rel="noopener noreferrer"&gt;Logitech G305&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While at work, my entire workflow revolves around the keyboard. My development environment resumes practically in just a terminal. On my browser, I use extensions to facilitate the control with the keyboard.&lt;/p&gt;

&lt;p&gt;The amount of interactions left to the mouse is small, that’s why I never paid much attention to it. But after a lot of time using &lt;a href="https://www.apple.com/shop/product/MLA02LL/A/magic-mouse-2-silver" rel="noopener noreferrer"&gt;Apple’s Magic Mouse&lt;/a&gt;, I decided to invest in a device focused on ergonomics, my wrist was killing me, even with relatively low usage.&lt;/p&gt;

&lt;p&gt;I learned about trackballs, and after reading a lot of praising reviews decided to give it a shot. Loved it!&lt;/p&gt;

&lt;p&gt;Ended up choosing a &lt;a href="https://www.kensington.com/p/products/electronic-control-solutions/trackball-products/expert-mouse-wireless-trackball/" rel="noopener noreferrer"&gt;Kensington Expert Mouse&lt;/a&gt;, and never looked back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headphones
&lt;/h2&gt;

&lt;p&gt;What kind of developer setup does not have headphones? Especially now, that all the meetings happen remotely, headphones are an extreme necessity.&lt;/p&gt;

&lt;p&gt;Most of the time, I use &lt;a href="https://www.apple.com/airpods-2nd-generation/" rel="noopener noreferrer"&gt;Apple’s Airpods&lt;/a&gt;, which works great, except when you have a lot of stuff connected over Bluetooth. If that’s the case, you can face a lot of connectivity issues, like I have been facing ☹.&lt;/p&gt;

&lt;p&gt;While playing or listening to music, I use the &lt;a href="https://north-america.beyerdynamic.com/dt-150.html" rel="noopener noreferrer"&gt;Beyerdynamic DT 150&lt;/a&gt;, the famous German tank, super well built, the rustic, weird, retro design is a con for some, I dig it. I hook these up to a &lt;a href="https://www.fiio.com/k3" rel="noopener noreferrer"&gt;Fiio K3&lt;/a&gt;, a headphone amplifier, and Digitial Audio Converter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chair
&lt;/h2&gt;

&lt;p&gt;For budget reasons, I chose the &lt;a href="https://www.ikea.com/de/de/p/jaervfjaellet-drehstuhl-gunnared-dunkelgrau-30363594/" rel="noopener noreferrer"&gt;JÄRVFJÄLLET&lt;/a&gt; from IKEA. It is a good looking chair, but I don’t find it very comfortable, the neck/head support feels weirdly positioned, the arms have no adjustments whatsoever, among other things.&lt;/p&gt;

&lt;p&gt;I mean, what could I expect from a 200 euros chair? High end, good quality office chairs can easily pass the 1000 euro mark. It is an investment that will last for a long, long time, one that I plan to make shortly.&lt;/p&gt;

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

&lt;p&gt;At least for me, it seems that my workspace will always be a work in progress. While writing this post, I noticed how many things I want to improve, swap, or change, and it is a lot!&lt;/p&gt;

&lt;p&gt;Even with all the details that can be improved, this is still the best setup I have ever had, and proved time and time again to have been a wise investment. It makes my time at the computer that much more enjoyable and comfortable, which is essential during these prolonged indoor times we have been going through.&lt;/p&gt;

</description>
      <category>setup</category>
      <category>mac</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
