<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>The Minimalist Developer</title>
    <subtitle>Software engineering, a bit of management, geek-outs, gadgets, some opinions, and all that good stuff</subtitle>
    <link rel="self" type="application/atom+xml" href="https://www.theminimalistdeveloper.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-08T08:30:00+00:00</updated>
    <id>https://www.theminimalistdeveloper.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Don&#x27;t Put All Your Tokens in One Basket</title>
        <published>2026-07-08T08:30:00+00:00</published>
        <updated>2026-07-08T08:30:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/dont-put-all-your-tokens-in-one-basket/"/>
        <id>https://www.theminimalistdeveloper.com/dont-put-all-your-tokens-in-one-basket/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/dont-put-all-your-tokens-in-one-basket/">&lt;p&gt;AI is present everywhere these days, whether you like it or not, especially in our industry.&lt;&#x2F;p&gt;
&lt;p&gt;The degree of reliance goes to extremes, to the point where a service disruption means no work gets done at all.&lt;&#x2F;p&gt;
&lt;p&gt;I am not here to debate the pros and cons of AI in development, but to explore alternative strategies to reduce risks and tame the costs of money-hungry AI machines.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-we-are-trying-to-avoid&quot;&gt;What we are trying to avoid&lt;&#x2F;h2&gt;
&lt;p&gt;Outages continue to be a regular occurrence. &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;status.anthropic.com&quot;&gt;Anthropic&#x27;s status page&lt;&#x2F;a&gt; paints a good picture of the situation, with incidents practically every day. &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.incidenthub.cloud&#x2F;github-reliability-outage-history-2025-2026&quot;&gt;GitHub Copilot&lt;&#x2F;a&gt; struggles to keep up with demand, just to name a few.&lt;&#x2F;p&gt;
&lt;p&gt;Rate limits have tightened as providers shift from heavily subsidized to trying to (unsuccessfully) monetise.&lt;&#x2F;p&gt;
&lt;p&gt;In early 2025, OpenAI lowered default tokens-per-minute caps for new accounts, and Anthropic introduced stricter tier limits that require &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;finance.biggo.com&#x2F;news&#x2F;aHDqzJ0BDPbb-ItTijCV&quot;&gt;escalated payment plans to bypass&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Regional access remains unpredictable. Anthropic updated its list of supported countries in early 2025, &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anthropic.com&#x2F;news&#x2F;updating-restrictions-of-sales-to-unsupported-regions&quot;&gt;dropping service in several markets&lt;&#x2F;a&gt; without advance notice, while OpenAI&#x27;s terms continue to shift in response to evolving data sovereignty rules. A global product can find its core feature legally inaccessible in a key jurisdiction overnight not because the code changed, but because a compliance checkbox was unticked.&lt;&#x2F;p&gt;
&lt;p&gt;Not to mention the increasing involvement of governmental entities actively in &quot;regulation&quot; with less-than-opaque reasoning, like the debacle around Anthropic&#x27;s &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anthropic.com&#x2F;news&#x2F;fable-mythos-access&quot;&gt;Fable 5 (their latest model family)&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In a multi-jurisdiction world, trusting a single provider&#x27;s availability map is an operational gamble.&lt;&#x2F;p&gt;
&lt;p&gt;Those are the headlines, broadcasted everywhere. There are subtle and more prevalent issues that can be just as damaging for teams that heavily rely on AI.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;silent-downgrades&quot;&gt;Silent Downgrades&lt;&#x2F;h3&gt;
&lt;p&gt;The API stays identical, but the model behind it doesn&#x27;t. Your prompts stop working as expected, and nobody sends a changelog.
We see this particular example with the Fable 5 now back in the picture, which &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;platform.claude.com&#x2F;cookbook&#x2F;fable-5-fallback-billing-guide&quot;&gt;will fall back to Opus 4.8 for various tasks&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This could be due to a myriad of reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A&#x2F;B testing&lt;&#x2F;li&gt;
&lt;li&gt;Cost optimization&lt;&#x2F;li&gt;
&lt;li&gt;Safety or policy updates.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The reason is not really important for us, LLM&#x27;s are not known for their determinism when you add all those extra variables on top it doesn&#x27;t help.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;creeping-billing&quot;&gt;Creeping billing&lt;&#x2F;h3&gt;
&lt;p&gt;Unlike the early days, the &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.forbes.com&#x2F;sites&#x2F;jemmagreen&#x2F;2026&#x2F;07&#x2F;02&#x2F;ai-costs-more-than-the-people-it-replaced&#x2F;&quot;&gt;open buffet of tokens is closed&lt;&#x2F;a&gt;. We are seeing the landscape shift from attracting users to desperately showing the world that the AI money-burning-machine can be a sustainable business model.&lt;&#x2F;p&gt;
&lt;p&gt;Providers employ many tactics to make sure their IPO is within reach: they deprecate old model IDs, or quietly remove the most cost-efficient variants from their catalogues. Your prompts still work, but the underlying model has been swapped to a more expensive one without a notice period.&lt;&#x2F;p&gt;
&lt;p&gt;In 2025, OpenAI began enforcing usage tiers that unlock cheaper rates only after a monthly spend threshold, meaning small teams and startups pay a premium simply for being small. The economies of scale don&#x27;t get passed down; they get priced out.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.openai.com&#x2F;api&#x2F;docs&#x2F;pricing&quot;&gt;Token pricing&lt;&#x2F;a&gt; has also been updated to a more complex and difficult-to-predict model: input, output, and even per-route within the same model family have different prices.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;strategies&quot;&gt;Strategies&lt;&#x2F;h2&gt;
&lt;p&gt;The following strategies are not exclusive; they work best when combined into a layered approach that matches your team&#x27;s risk tolerance and budget.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;standardise-on-the-openai-api-format&quot;&gt;Standardise on the OpenAI API format&lt;&#x2F;h3&gt;
&lt;p&gt;OpenAI API design has become the de facto standard for LLM interaction. Most providers and local runtimes (Ollama, llama.cpp servers, vLLM, etc.) support this interface, assuming your stack can target it.&lt;&#x2F;p&gt;
&lt;p&gt;Write your code against the interface, not against a specific vendor. Swapping providers becomes a simple configuration change, not a code rewrite. This decoupling protects you from vendor lock-in and enables flexible experimentation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;choose-the-right-tool-for-the-job&quot;&gt;Choose the right tool for the job&lt;&#x2F;h3&gt;
&lt;p&gt;Not everything requires a frontier bazooka. Most people would be surprised how far smaller models have come. Running locally (or self-hosted) won&#x27;t beat frontier models on raw capability, but they don&#x27;t disappear, don&#x27;t raise prices, and don&#x27;t relay information home. For a lot of tasks—classification, summarisation, structured extraction—they&#x27;re already good enough.&lt;&#x2F;p&gt;
&lt;p&gt;Consider a tiered approach for models:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Baseline models, where you can balance speed and performance for most of everyday tasks: Claude Sonnet 4.6, GPT-4o, DeepSeek v3.2&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Smaller, quicker models for completion or simple tasks: Qwen2.5-Coder 1.5B, DeepSeek-Coder 3B&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Frontier models, for tasks that require deep, nuanced understanding, like planning a difficult technical solution: Claude Opus 4.8, DeepSeek v4-pro, GPT-5.5&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It is prudent to also maintain a chain of fallbacks with different providers mechanism ensuring that your core functionality remains robust and independent.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;abstract-the-provider-behind-your-own-layer&quot;&gt;Abstract the provider behind your own layer&lt;&#x2F;h3&gt;
&lt;p&gt;Don&#x27;t scatter SDK calls across your codebase. Route everything through one thin layer you control, ensuring a single point of management for all external interactions.&lt;&#x2F;p&gt;
&lt;p&gt;With this approach, you can easily switch models per task or per cost budget, add retries, timeouts, and a local fallback in one place, and log and evaluate outputs to catch silent downgrades.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;litellm&quot;&gt;LiteLLM&lt;&#x2F;h4&gt;
&lt;p&gt;You don&#x27;t have to build this layer yourself. There are a few robust projects like &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BerriAI&#x2F;litellm&quot;&gt;LiteLLM&lt;&#x2F;a&gt; which acts as a proxy and SDK that exposes a single OpenAI-compatible interface in front of 100+ providers—OpenAI, Anthropic, Bedrock, local Ollama, you name it.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;One interface, many backends: swap providers with a config change, not a rewrite.&lt;&#x2F;li&gt;
&lt;li&gt;Built-in retries, fallbacks, and per-model routing covering the abstraction concerns above, off the shelf.&lt;&#x2F;li&gt;
&lt;li&gt;Cost tracking and rate limiting in one place, so you can catch a &quot;premium tier&quot; surprise before it hits the invoice.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The point isn&#x27;t LiteLLM specifically, it&#x27;s that your code should talk to &lt;em&gt;your&lt;&#x2F;em&gt; boundary, and let something like this sit behind it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;own-your-data-and-prompts&quot;&gt;Own your data and prompts&lt;&#x2F;h3&gt;
&lt;p&gt;Keep prompts, evals, and any fine-tuning data versioned in your own repo. If you can rebuild your behaviour on a different model, you&#x27;re portable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Redundancy isn&#x27;t paranoia, it&#x27;s the same engineering discipline you&#x27;d apply to any critical dependency. You wouldn&#x27;t build on a single database with no backups and no migration path. AI providers deserve exactly that skepticism.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Illusion of Competence</title>
        <published>2026-06-26T17:00:00+00:00</published>
        <updated>2026-06-26T17:00:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/the-illusion-of-competence/"/>
        <id>https://www.theminimalistdeveloper.com/the-illusion-of-competence/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/the-illusion-of-competence/">&lt;h2 id=&quot;am-i-missing-something&quot;&gt;Am I Missing Something?&lt;&#x2F;h2&gt;
&lt;p&gt;We are four years into the &quot;AI revolution,&quot; and it brought along a lot of possibilities, misinformation, fear mongering, j&lt;&#x2F;p&gt;
&lt;p&gt;In the midst of all the nonsense and absurd claims, one always makes me scratch my head: &quot;Oh, now with AI, SaaS is dead! You can do it all yourself.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;It left me questioning myself for quite a while: is my sarcasm meter broken?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;might-not-be-that-easy&quot;&gt;Might Not Be That Easy&lt;&#x2F;h2&gt;
&lt;p&gt;This sounds strange to me because any reasonably seasoned software developer or manager has faced the same question for decades: should we buy or build?&lt;&#x2F;p&gt;
&lt;p&gt;When we calculate the cost of building, we have to weigh so many things: maintenance, domain know-how, infrastructure, support, scalability, security. And those are just the known requirements. We also need to consider the cost when things fail, and they always fail. What is the impact then?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;big-opportunities-for-problems&quot;&gt;Big Opportunities... for Problems&lt;&#x2F;h2&gt;
&lt;p&gt;The &quot;just write your own&quot; logic is perfectly fine for low-risk, low-complexity applications that you already know how to operate and maintain (and BTW, there are indeed a lot of micro SaaS ideas that fall into this category). Which raises the question: why would you be paying for it in the first place?&lt;&#x2F;p&gt;
&lt;p&gt;In any other scenario, an alarm starts ringing right behind my ear.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Hey, we pay so much for Stripe. For what? Just let Claude run free!&quot; said the overly confident CTO of a somewhat successful e-commerce company with three developers.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;How many of those developers have experience with payment systems, fraud detection, legislation, refund workflows, and the rest? Zero.&lt;&#x2F;p&gt;
&lt;p&gt;So they let Claude run free. Three months later, a silent rounding bug in their refund flow had quietly overcharged a chunk of customers. No fraud detection meant chargebacks piled up, and the payment processor flagged the account. The &quot;savings&quot; evaporated, plus the cost of the engineering scramble, the lost trust, and the legal review. The realization that they were out of their depth came expensive and late.&lt;&#x2F;p&gt;
&lt;p&gt;This might be an extreme example, but, scaled to their respective proportions, the same dynamic applies to almost everything.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;it-s-not-about-ai-itself&quot;&gt;It&#x27;s not about AI itself&lt;&#x2F;h2&gt;
&lt;p&gt;To be clear, this is not an argument against AI. AI is excellent at accelerating the parts you &lt;em&gt;do&lt;&#x2F;em&gt; understand: scaffolding the integrations, writing tests, generating boilerplate, documenting workflows. The distinction is between using AI to move faster on a problem you can reason about, versus using it to replace expertise you simply do not have. The former is leverage. The latter is a liability waiting to blow up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;AI is an immense help for so many professions, including development, but it&#x27;s not a silver bullet. Buy versus build never went away; AI just made it easier to pick the wrong answer with more confidence.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Minimalist blog with Zola, AWS CDK, and Tailwind CSS - Part 1</title>
        <published>2025-02-18T07:00:00+00:00</published>
        <updated>2025-02-18T07:00:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/minimalist-blog-with-zola-and-tailwindcss-part-1/"/>
        <id>https://www.theminimalistdeveloper.com/minimalist-blog-with-zola-and-tailwindcss-part-1/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/minimalist-blog-with-zola-and-tailwindcss-part-1/">&lt;h2 id=&quot;assumptions-clarifications-and-reasons&quot;&gt;Assumptions, clarifications, and reasons&lt;&#x2F;h2&gt;
&lt;p&gt;What are we going to do today? We&#x27;re going to build a minimalist blog using &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getZola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; (built with &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.org&quot;&gt;Rust&lt;&#x2F;a&gt;, btw), &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;cdk&quot;&gt;AWS CDK&lt;&#x2F;a&gt;, &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailwindcss.com&quot;&gt;Tailwind CSS&lt;&#x2F;a&gt;, and a tiny bit of &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typescriptlang.org&quot;&gt;Typescript&lt;&#x2F;a&gt;.&lt;&#x2F;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&#x2F;CD pipelines, nor any automation.&lt;&#x2F;p&gt;
&lt;p&gt;I can already feel some of you itching out to furiously type: Why not use &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vercel.com&quot;&gt;Vercel&lt;&#x2F;a&gt; &#x2F; Whatever other company that does the same thing &#x2F; whatever instead! :angry foaming face:&lt;&#x2F;p&gt;
&lt;p&gt;For a few reasons:&lt;&#x2F;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;&#x2F;li&gt;
&lt;li&gt;Familiarity with AWS and CDK.&lt;&#x2F;li&gt;
&lt;li&gt;I want to.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;With that out of the way, let&#x27;s move on.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;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;&#x2F;p&gt;
&lt;p&gt;The setup I had before in this blog before was a &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nextjs.org&quot;&gt;NextJS&lt;&#x2F;a&gt; &#x2F; Vercel &#x2F; Headless CMS combo. I hated it, way too many pieces for my use case, and didn&#x27;t align with my preferred workflow.&lt;&#x2F;p&gt;
&lt;p&gt;So I scraped that and started fresh with a few rules to guide the development:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The content has to be stored in &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.markdownguide.org&quot;&gt;Markdown&lt;&#x2F;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;&#x2F;li&gt;
&lt;li&gt;It has to be statically generated - I don&#x27;t want server-side render something that will never&#x2F;very unlikely to change.&lt;&#x2F;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;&#x2F;li&gt;
&lt;li&gt;The frontend setup should be simple and easy to extend.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With that in mind, I quickly narrowed down to a few challengers &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gatsbyjs.comg&quot;&gt;Gatsby&lt;&#x2F;a&gt; and &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&quot;&gt;Hugo&lt;&#x2F;a&gt; being the usual suspects.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;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;&#x2F;p&gt;
&lt;p&gt;Seemed too good to be true, but it isn&#x27;t. A healthy community, with over 14k stars on GitHub and good enough documentation? I am in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setup-the-project&quot;&gt;Setup the project&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;cdk&quot;&gt;CDK&lt;&#x2F;h3&gt;
&lt;p&gt;First, let&#x27;s install AWS CDK.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;# This will install the CDK command line tool globally&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; install -g aws-cdk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the condensed version, you can find more information in their &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;cdk&#x2F;v2&#x2F;guide&#x2F;getting_started.html&quot;&gt;Getting started page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, create the blog folder, in our example it will be &lt;em&gt;my-blog&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; my-blog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ED8796;font-style: italic;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; my-blog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; cdk init app --language typescript&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above commands will create the initial setup for our infrasctucture in Typescript with a Git repository.&lt;&#x2F;p&gt;
&lt;p&gt;I am assuming you have set up your AWS account and credentials, if not follow the &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;cdk&#x2F;v2&#x2F;guide&#x2F;prerequisites.html&quot;&gt;official tutorial&lt;&#x2F;a&gt; before reading any further.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zola&quot;&gt;Zola&lt;&#x2F;h3&gt;
&lt;p&gt;Make sure you have Zola installed. They have a pretty &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getZola.org&#x2F;documentation&#x2F;getting-started&#x2F;installation&#x2F;&quot;&gt;extensive list of ways of installing it&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, let&#x27;s set up our blog. Within the &lt;em&gt;my-blog&lt;&#x2F;em&gt; folder, we created in the previous step, run the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;zola&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; init my-blog -f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that we used the &lt;em&gt;-f&lt;&#x2F;em&gt; flag, which means to force the creation of the blog structure within a folder that already contains files.&lt;&#x2F;p&gt;
&lt;p&gt;This command will prompt a few questions, among them if you want to use &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sass-lang.com&quot;&gt;SaSS&lt;&#x2F;a&gt; compilation and if you would like to have a search enabled.&lt;&#x2F;p&gt;
&lt;p&gt;For the purposes of this example, we will answer no to both of them, don&#x27;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;&#x2F;p&gt;
&lt;p&gt;After, that you should have your blog folder set up and can already see it in action.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;zola&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; serve&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Accessing &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;127.0.0.1:1111&quot;&gt;http:&#x2F;&#x2F;127.0.0.1:1111&lt;&#x2F;a&gt; should show the standard Zola welcome page.&lt;&#x2F;p&gt;
&lt;p&gt;Congratulations, you made a website.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tailwind-css&quot;&gt;Tailwind CSS&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;To install it, from the &lt;em&gt;my-blog&lt;&#x2F;em&gt; folder:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; install tailwindcss @tailwind&#x2F;cli&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we should have all the pieces in place so we can start to put our blog together.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;infrastructure&quot;&gt;Infrastructure&lt;&#x2F;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;&#x2F;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 class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;s3&#x2F;&quot;&gt;S3&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;We will leverage &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;cloudfront&#x2F;getting-started&#x2F;S3&#x2F;?nc1=h_ls&quot;&gt;CloudFront&lt;&#x2F;a&gt; to enable a much faster, reliable, and cheap way to deliver our website.&lt;&#x2F;p&gt;
&lt;p&gt;This setup will look something like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.theminimalistdeveloper.com&#x2F;minimalist-blog-with-zola-and-tailwindcss-part-1&#x2F;.&#x2F;my-blog-infrastructure-diagram.svg&quot; alt=&quot;Diagram for the infrastructure, a Cloudfront distribution pointing to a S3 bucket located in us-east-1&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;s3-bucket&quot;&gt;S3 Bucket&lt;&#x2F;h3&gt;
&lt;p&gt;Open your infrastructure stack definition at &lt;em&gt;.&#x2F;lib&#x2F;my-blog-stack.ts&lt;&#x2F;em&gt; and add the follow resource in the body of the constructor function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; This is where we will store all the assets generated from Zola, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; essentially our entire website.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; website&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;font-weight: bold;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_s3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Bucket&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;my-blog&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; This speeds up the transfer of our files to S3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      transferAcceleration&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; This tells S3 to only allow access to our bucket through SSL &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      enforceSSL&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;* &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        This tells S3 to remove all the contents of the bucket when we remove &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        the stack. This is particularly useful if you decide to have multiple &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        instances of the stack to let&amp;#39;s say test a feature. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        If you don&amp;#39;t add this when you remove the stack, it will get stuck &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        because the bucket will be filled with files and the Stack will refuse &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        to continue the removal leading to manual intervention.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      removalPolicy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;RemovalPolicy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;DESTROY&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; This is very important, we don&amp;#39;t want anyone from the outside world to&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; be able to access our files directly&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      blockPublicAccess&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_s3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;BlockPublicAccess&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;BLOCK_ALL&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&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&#x27;s files.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; cloudfrontOAI&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;font-weight: bold;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;OriginAccessIdentity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt;      this&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;      &amp;quot;MyOriginAccessIdentity&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;      {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        comment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;Allows CloudFront to reach the website bucket&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;      },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    website&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;grantRead&lt;&#x2F;span&gt;&lt;span&gt;(cloudfrontOAI)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; s3origin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;font-weight: bold;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront_origins&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;S3Origin&lt;&#x2F;span&gt;&lt;span&gt;(website&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      originAccessIdentity&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cloudfrontOAI&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&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&#x27;s. That is because CloudFront does not resolve paths ending in &#x27;&#x2F;&#x27; to &#x27;&#x2F;index.html&#x27; like Zola will create for us.&lt;&#x2F;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;&#x2F;strong&gt; event.&lt;&#x2F;p&gt;
&lt;p&gt;This event happens before the request reaches CloudFront&#x27;s cache, allowing us to direct the selected requests to the right files.&lt;&#x2F;p&gt;
&lt;p&gt;This is the function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; indexRedirector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;font-weight: bold;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;Function&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;FunctionCode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;fromInline&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;      function handler(event) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;          var request = event.request;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;          var uri = request.uri;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;          if (uri.endsWith(&amp;#39;&#x2F;&amp;#39;)) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;            request.uri += &amp;#39;index.html&amp;#39;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;          }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;          else if (!uri.includes(&amp;#39;.&amp;#39;)) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;            request.uri += &amp;#39;&#x2F;index.html&amp;#39;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;          }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;          return request;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;      `&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      runtime&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;FunctionRuntime&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;JS_2_0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, we get to our CloudFront distribution, that will look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; cdn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;font-weight: bold;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Distribution&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;my-blog-cdn&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; This determines which object to look for in the root folder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      defaultRootObject&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;index.html&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      minimumProtocolVersion&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;SecurityPolicyProtocol&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;TLS_V1_2_2021&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;* &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      Behaviors determine how CloudFront handles the assets. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      In our case we will only need the default one.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      defaultBehavior&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; Origin tells CloudFront where to look for the files being requested&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        origin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; s3origin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; Please, compress the files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        compress&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; This is very important, determins which HTTP methods we allow on &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; CloudFront, in our case only GET and HEAD methods&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        allowedMethods&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;AllowedMethods&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;ALLOW_GET_HEAD_OPTIONS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;* &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        This determines how we want CloudFront to behave with HTTP and HTTPS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        protocols. We will ask to redirect HTTP requests to HTTPS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        viewerProtocolPolicy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ViewerProtocolPolicy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;REDIRECT_TO_HTTPS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; Cache both methods requests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cachedMethods&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;CachedMethods&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;CACHE_GET_HEAD_OPTIONS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; We use a managed cache policy called caching optimized&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cachePolicy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;CachePolicy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;CACHING_OPTIMIZED&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; here we add the function that will take care of adding the extra &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; index.html bit on the matching url&amp;#39;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        functionAssociations&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;          {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; indexRedirector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            eventType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_cloudfront&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;FunctionEventType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;VIEWER_REQUEST&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;          },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;      },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&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;&#x2F;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;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;font-weight: bold;&quot;&gt;    new&lt;&#x2F;span&gt;&lt;span&gt; cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_s3_deployment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;BucketDeployment&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;my-blog-deploy-website&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; Point to the folder where Zola will put the output of the website&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      sources&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aws_s3_deployment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Source&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;asset&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(__dirname&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;..&#x2F;public&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      )]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; Tell to which S3 bucket to upload to &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      destinationBucket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; website&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; Point to which Cloudfront distribution should be used&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      distribution&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cdn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; Tell which path should be cleaned when deployed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      distributionPaths&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;&#x2F;*&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;deployment&quot;&gt;Deployment&lt;&#x2F;h2&gt;
&lt;p&gt;Alright, now we can already start deploying.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;# First build the website&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;zola&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;# Then deploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;cdk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; deploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If everything went well you should see your Stack &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;reference-arns.html&quot;&gt;ARN&lt;&#x2F;a&gt; at the end of the output.&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;See you in part 2!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Take control of your learning journey</title>
        <published>2025-02-10T07:25:00+00:00</published>
        <updated>2025-02-10T07:25:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/take-control-of-your-learning-journey/"/>
        <id>https://www.theminimalistdeveloper.com/take-control-of-your-learning-journey/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/take-control-of-your-learning-journey/">&lt;h2 id=&quot;legacy&quot;&gt;Legacy&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Netflix? Yes. Even Google? Oh yes.&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve experienced both myself, it&#x27;s not fun.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;harsh-truth&quot;&gt;Harsh Truth&lt;&#x2F;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;&#x2F;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;&#x2F;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.
And to a certain extent that is a good thing, hyper fixating on tooling is a dangerous and often disastrous path.&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;h2 id=&quot;the-work-never-ends&quot;&gt;The Work Never Ends&lt;&#x2F;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;&#x2F;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;&#x2F;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;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;h2 id=&quot;ok-now-what&quot;&gt;Ok, now what?&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Instead of giving a list of concrete ideas, here are some approaches that worked for me.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-copy&quot;&gt;1. Copy&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Music players, social networks, command line tools, wrappers to facilitate repetitive work, etc.&lt;&#x2F;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;&#x2F;p&gt;
&lt;h3 id=&quot;2-scratch-your-own-itch&quot;&gt;2. Scratch your own itch&lt;&#x2F;h3&gt;
&lt;p&gt;The good ol&#x27; strategy of trying to solve a need you already have.&lt;&#x2F;p&gt;
&lt;p&gt;Do you love Spotify but would prefer to control it via Neovim? Good one.&lt;&#x2F;p&gt;
&lt;p&gt;How about a nicer way to navigate your PRs? Great.&lt;&#x2F;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.
Do that for a week, and you will probably be surprised by the amount of things you will come up with.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-tactical&quot;&gt;3. Tactical&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;An awesome tool to play around and figure out trends is Google Trends.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;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&#x27;s not what they are there for.&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;That&#x27;s why I strongly advocate for side projects, there are huge benefits when you invest those extra hours.&lt;&#x2F;p&gt;
&lt;p&gt;It can make you more fullfilled, sometimes happier, but &lt;strong&gt;always&lt;&#x2F;strong&gt; better at your craft.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why Everybody Wants To Get Rid Of Software Developers?</title>
        <published>2025-01-16T18:25:00+00:00</published>
        <updated>2025-01-16T18:25:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/why-everybody-wants-to-get-rid-of-sotware-developers/"/>
        <id>https://www.theminimalistdeveloper.com/why-everybody-wants-to-get-rid-of-sotware-developers/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/why-everybody-wants-to-get-rid-of-sotware-developers/">&lt;p&gt;The reason might be simply because they are expensive. But, as usual, I believe there is more to it.&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Initially, I thought it was purely financially motivated. If you can make it simpler and&#x2F;or faster, it will be cheaper, but I believe there is more to it.&lt;&#x2F;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;&#x2F;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;&#x2F;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;&#x2F;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;&#x2F;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&#x27;t that be amazing?&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Your genius would shine without being obfuscated by lazy, awkward, slow, and overpaid developers.&lt;&#x2F;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&#x27;t be directly translated to software without considering contextual, technical, and non-technical aspects that directly impact a system&#x27;s design.&lt;&#x2F;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;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;See, I am not even getting into the quality of the output of those tools, which arguably, aren&#x27;t particularly good to begin with.&lt;&#x2F;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.
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&#x27;t know.&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;That&#x27;s why it is the first thing I probe for whenever I am hiring for our teams.&lt;&#x2F;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&#x27;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;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;And my friends, that is a good thing.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Setting Up Typescript Project From Scratch</title>
        <published>2020-11-29T10:25:00+00:00</published>
        <updated>2020-11-29T10:25:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/setting-up-typescript-project-from-scratch/"/>
        <id>https://www.theminimalistdeveloper.com/setting-up-typescript-project-from-scratch/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/setting-up-typescript-project-from-scratch/">&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;&#x2F;h2&gt;
&lt;p&gt;You don&#x27;t want to read through all those steps?
Dive in straight into coding, just clone&#x2F;download&#x2F;fork &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;theminimalistdeveloper&#x2F;base-typescript-project&quot;&gt;this repository&lt;&#x2F;a&gt; with the resulting base project of this post 😀.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;Whenever learning a new language after &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.theminimalistdeveloper.com&#x2F;setting-up-neovim-for-typescript-development&#x2F;&quot;&gt;configuring a proper development environment&lt;&#x2F;a&gt;, set up a project from scratch is the next step on my list.&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Project structure&lt;&#x2F;strong&gt;: Folder structure, Git, NPM&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Unit test setup&lt;&#x2F;strong&gt;: Jest&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Style guide&lt;&#x2F;strong&gt;: Airbnb style guide for Typescript&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;NPM Scripts&lt;&#x2F;strong&gt;: Wrap up common commands in NPM scripts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Pre commit hooks&lt;&#x2F;strong&gt;: To ensure we don&#x27;t tarnish our immaculate repository&lt;&#x2F;li&gt;
&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Also, everything here is aimed towards *&lt;strong&gt;nix&lt;&#x2F;strong&gt; environments, either be some Linux flavor or MacOs, with &lt;strong&gt;NodeJS&lt;&#x2F;strong&gt; and &lt;strong&gt;Git&lt;&#x2F;strong&gt; installed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-initiate-the-project&quot;&gt;1 - Initiate the Project&lt;&#x2F;h3&gt;
&lt;p&gt;Define the folder name that will house our project. In this case, let&#x27;s call it &lt;strong&gt;ts-project&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; -p ts-project&#x2F;{src,tests&#x2F;unit&#x2F;src}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above command will generate this structure:&lt;&#x2F;p&gt;
&lt;pre&gt;
ts-project
├── src
└── tests
    └── unit
        └── src
&lt;&#x2F;pre&gt;
&lt;p&gt;Hop into the project&#x27;s folder.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ED8796;font-style: italic;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ts-project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Initiate an empty Git Repository:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Add a &lt;strong&gt;.gitignore&lt;&#x2F;strong&gt; file at the root of the project with the following content:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;node_modules&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dist&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which will tell Git to not track the changes on those folders.&lt;&#x2F;p&gt;
&lt;p&gt;Initiate an NPM project. The &lt;strong&gt;-y&lt;&#x2F;strong&gt; tells NPM to accept all the default settings:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; init -y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Install Typescript:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; install --save-dev typescript&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&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;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Initiate Typescript by issuing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; tsc --init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This line deserves a word or two. Alongside NPM, it is installed another tool called &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;npx&quot;&gt;NPX&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;The &lt;strong&gt;tsc&lt;&#x2F;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;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;message TS6071: Successfully created a tsconfig.json file.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It creates a configuration file called &lt;strong&gt;tsconfig.json&lt;&#x2F;strong&gt; with parameters necessary for Typescript to work properly.&lt;&#x2F;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;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;compilerOptions&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;target&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;es5&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;commonjs&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;strict&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;esModuleInterop&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;skipLibCheck&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;forceConsistentCasingInFileNames&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For a detailed description of what each of these fields means, please check the official documentation right &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;tsconfig&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s tweak this a little bit. Add two new keys to the compiler options&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;outDir&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;dist&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;sourceMap&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;outDir&lt;&#x2F;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;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;sourceMap&lt;&#x2F;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;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And at the root we add:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;include&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;.&#x2F;src&#x2F;**&#x2F;*&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which tells the compiler to take everything from the source (src) folder.&lt;&#x2F;p&gt;
&lt;p&gt;The end result is something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  &amp;quot;compilerOptions&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;target&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;es5&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;module&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;commonjs&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;strict&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;esModuleInterop&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;skipLibCheck&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;forceConsistentCasingInFileNames&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;outDir&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;dist&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  &amp;quot;include&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;.&#x2F;src&#x2F;**&#x2F;*&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;2-unit-tests&quot;&gt;2 - Unit Tests&lt;&#x2F;h3&gt;
&lt;p&gt;For unit tests, I have been using &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jestjs.io&#x2F;en&#x2F;&quot;&gt;Jest&lt;&#x2F;a&gt; for quite some time now, no complaints.&lt;&#x2F;p&gt;
&lt;p&gt;Very straight forward and simple testing framework.&lt;&#x2F;p&gt;
&lt;p&gt;To install all the packages necessary run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; install --save-dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  jest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  babel-jest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  @babel&#x2F;core&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  @babel&#x2F;preset-env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  @babel&#x2F;preset-typescript&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  @types&#x2F;jest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then add a &lt;strong&gt;babe.config.js&lt;&#x2F;strong&gt; at the root of the project with the content:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;font-style: italic;&quot;&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;font-style: italic;&quot;&gt;exports&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  presets&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;#39;@babel&#x2F;preset-env&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;, {&lt;&#x2F;span&gt;&lt;span&gt; targets&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt; node&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;#39;current&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; } }&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;#39;@babel&#x2F;preset-typescript&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And our testing setup is done.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-style-guide-and-linting&quot;&gt;3 - Style guide and linting&lt;&#x2F;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 class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;airbnb&#x2F;javascript&quot;&gt;Airbnb style guide for Javascript&lt;&#x2F;a&gt; for almost two years, and love it. Helps to fix smaller mistakes literally pointing out to you.&lt;&#x2F;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 class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;eslint-config-airbnb-typescript&quot;&gt;eslint-config-airbnb-typescript&lt;&#x2F;a&gt;, which is a drop-in replacement for the normal &lt;strong&gt;eslint-config-airbnb&lt;&#x2F;strong&gt; but with all the Typescript goodness.&lt;&#x2F;p&gt;
&lt;p&gt;To install, run the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; install --save-dev&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    eslint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    eslint-config-airbnb-typescript&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    eslint-plugin-import@^2.22.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    @typescript-eslint&#x2F;eslint-plugin@^4.4.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And add &lt;strong&gt;.eslintrc.js&lt;&#x2F;strong&gt; to the project root with the content:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;font-style: italic;&quot;&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;font-style: italic;&quot;&gt;exports&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;#39;airbnb-typescript&#x2F;base&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  parserOptions&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    project&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;#39;.&#x2F;tsconfig.json&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In case you went through my last post &quot;&lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.theminimalistdeveloper.com&#x2F;setting-up-neovim-for-typescript-development&#x2F;&quot;&gt;Setting up Neovim for typescript development&lt;&#x2F;a&gt;&quot; you will notice that this style guide uses Eslint, and we configured the only tsserver.
To add Coc support for Eslint run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;:CocInstall&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; coc-eslint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Check out its &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neoclide&#x2F;coc-eslint&quot;&gt;documentation&lt;&#x2F;a&gt; to learn more about the extension.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;4-npm-scripts&quot;&gt;4 - NPM Scripts&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s leverage the &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.npmjs.com&#x2F;cli&#x2F;v6&#x2F;using-npm&#x2F;scripts&quot;&gt;NPM scripts&lt;&#x2F;a&gt; system to facilitate interacting with the tooling we just set up.&lt;&#x2F;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&#x2F;CD pipelines. So in case, you decide to change your testing library or build process, we can simply change it in one place.&lt;&#x2F;p&gt;
&lt;p&gt;Add this piece of code at the root of the package.json:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;scripts&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;jest&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;lint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;eslint&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;compile&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;quot;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;tsc&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&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;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;# This will run the testing library Jest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; run test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;# This will run the linting&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; run lint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;# This will run the compilation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; run compile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;5-pre-commit-hooks&quot;&gt;5 - Pre-Commit Hooks&lt;&#x2F;h3&gt;
&lt;p&gt;Finishing up with some fail-safes, it can make our lifes much easier. &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Customizing-Git-Git-Hooks&quot;&gt;Git hook&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;In this example, we will use a package called &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;pre-commit&quot;&gt;pre-commit&lt;&#x2F;a&gt; to run our scripts before the commits. To install it, run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; install --save-dev pre-commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then add this to package.json:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;pre-commit&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;test&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;lint&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;    &amp;quot;compile&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&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;&#x2F;p&gt;
&lt;h3 id=&quot;6-testing&quot;&gt;6 - Testing&lt;&#x2F;h3&gt;
&lt;p&gt;With everything in place, let&#x27;s write a &quot;hello world&quot; and test it.
Add an &lt;strong&gt;index.ts&lt;&#x2F;strong&gt; to your &lt;strong&gt;src&lt;&#x2F;strong&gt; folder, located at the root of the project with this content:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;**&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; * Hello world function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;param&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt; name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; helloWorld&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; `Hello world, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;${&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;export default&lt;&#x2F;span&gt;&lt;span&gt; helloWorld&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And add an &lt;strong&gt;index.spec.ts&lt;&#x2F;strong&gt; at &lt;strong&gt;tests&#x2F;unit&#x2F;src&lt;&#x2F;strong&gt; with this content;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; helloWorld&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;#39;..&#x2F;..&#x2F;..&#x2F;src&#x2F;index&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;#39;Hello world works&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;, ()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;    expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;helloWorld&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;#39;Foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;toBe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;#39;Hello world, Foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, from the command line at the root of the project, run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; run lint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; run test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; run compile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which should result in something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ts-project@1.0.0 lint &#x2F;Users&#x2F;username&#x2F;ts-project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; eslint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ts-project@1.0.0 test &#x2F;Users&#x2F;username&#x2F;ts-project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; jest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; PASS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  tests&#x2F;unit&#x2F;src&#x2F;index.spec.ts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;  ✓&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; Hello world works&lt;&#x2F;span&gt;&lt;span&gt; (2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ms&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; Suites:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; passed,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Tests:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;       1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; passed,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Snapshots:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;   0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Time:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;        0.898&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; s, estimated&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Ran&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; all test suites.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ts-project@1.0.0 compile &#x2F;Users&#x2F;username&#x2F;ts-project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; tsc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ve made it!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Setting Up Neovim For Typescript Development</title>
        <published>2020-11-23T19:00:00+00:00</published>
        <updated>2020-11-23T19:00:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/setting-up-neovim-for-typescript-development/"/>
        <id>https://www.theminimalistdeveloper.com/setting-up-neovim-for-typescript-development/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/setting-up-neovim-for-typescript-development/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;First things first, right? Yes. So, I am learning &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;&quot;&gt;Typescript&lt;&#x2F;a&gt; whenever I start learning a new programming language, I begin by setting up a development environment.&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Since my weapon of choice is &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;&quot;&gt;Neovim&lt;&#x2F;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;&#x2F;p&gt;
&lt;h2 id=&quot;requirements&quot;&gt;Requirements&lt;&#x2F;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&#x27;t panic! Check out &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rafaelnexus.com&#x2F;tutorials&#x2F;what-is-neovim-and-how-to-install-it-with-python-support&#x2F;&quot;&gt;this&lt;&#x2F;a&gt; short and straight to the point post on what is Neovim and how to install it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;git&quot;&gt;Git&lt;&#x2F;h3&gt;
&lt;p&gt;🔗 &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;&quot;&gt;git-scm.com&lt;&#x2F;a&gt;&lt;&#x2F;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;&#x2F;p&gt;
&lt;h3 id=&quot;nodejs&quot;&gt;NodeJS&lt;&#x2F;h3&gt;
&lt;p&gt;🔗 &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nodejs.org&#x2F;en&#x2F;&quot;&gt;nodejs.org&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We need to, you know, run the code after compiling it. I currently am using version 12.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;plug&quot;&gt;Plug&lt;&#x2F;h3&gt;
&lt;p&gt;🔗 &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;junegunn&#x2F;vim-plug&quot;&gt;github.com&#x2F;junegunn&#x2F;vim-plug&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Plug is a plugin manager for Vim&#x2F;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;&#x2F;p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;coc&quot;&gt;CoC&lt;&#x2F;h3&gt;
&lt;p&gt;🔗 &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neoclide&#x2F;coc.nvim&quot;&gt;github.com&#x2F;neoclide&#x2F;coc.nvim&lt;&#x2F;a&gt;&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;The installation of the CoC is very straight forward. Simply add this line to your init file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Plug &amp;#39;neoclide&#x2F;coc.nvim&amp;#39;, {&amp;#39;branch&amp;#39;: &amp;#39;release&amp;#39;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And run on Neovim:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:PlugInstall&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&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;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;source &#x2F;path&#x2F;to&#x2F;your&#x2F;init.vim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;coc-tsserver-extension&quot;&gt;CoC Tsserver extension&lt;&#x2F;h3&gt;
&lt;p&gt;🔗 &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neoclide&#x2F;coc-tsserver&quot;&gt;github.com&#x2F;neoclide&#x2F;coc-tsserver&lt;&#x2F;a&gt;&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;The extension in question is called Tsserver, which is a language server for Typescript and Javascript.&lt;&#x2F;p&gt;
&lt;p&gt;To install, run this command from Neovim:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:CocInstall coc-tsserver&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To check if everything went as expected, run this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:CocList extensions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&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;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+ coc-tsserver 1.5.6 ~&#x2F;.config&#x2F;coc&#x2F;extensions&#x2F;node_modules&#x2F;coc-tsserver&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That means that everything is correct!&lt;&#x2F;p&gt;
&lt;p&gt;So, what can we expect from this extension?
Here is the feature list from the official Github repository:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Supports javascript &amp;amp; typescript and jsx&#x2F;tsx.&lt;&#x2F;p&gt;
&lt;p&gt;Installs typings automatically.&lt;&#x2F;p&gt;
&lt;p&gt;Commands to work with tsserver, including:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;tsserver.reloadProjects&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;tsserver.openTsServerLog&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;tsserver.goToProjectConfig&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;tsserver.restart&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;tsserver.organizeImports&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;tsserver.watchBuild&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Code completion support.&lt;&#x2F;p&gt;
&lt;p&gt;Go to definition.&lt;&#x2F;p&gt;
&lt;p&gt;Code validation.&lt;&#x2F;p&gt;
&lt;p&gt;Document highlight.&lt;&#x2F;p&gt;
&lt;p&gt;Document symbols of current buffer.&lt;&#x2F;p&gt;
&lt;p&gt;Folding and folding range of current buffer.&lt;&#x2F;p&gt;
&lt;p&gt;Format current buffer, range format, and format on type.&lt;&#x2F;p&gt;
&lt;p&gt;Hover for documentation.&lt;&#x2F;p&gt;
&lt;p&gt;Implementations codeLens and references codeLens.&lt;&#x2F;p&gt;
&lt;p&gt;Organize imports command.&lt;&#x2F;p&gt;
&lt;p&gt;Quickfix using code actions.&lt;&#x2F;p&gt;
&lt;p&gt;Code refactor using code actions.&lt;&#x2F;p&gt;
&lt;p&gt;Find references.&lt;&#x2F;p&gt;
&lt;p&gt;Signature help.&lt;&#x2F;p&gt;
&lt;p&gt;Rename symbols support.&lt;&#x2F;p&gt;
&lt;p&gt;Rename imports on file rename, require watchman installed in your $PATH.&lt;&#x2F;p&gt;
&lt;p&gt;Search for workspace symbols.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;A pretty sweet list, huh?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;As we&#x27;ve seen, it is not that difficult to have a complete Typescript setup running with Neovim and CoC in no time.
There is so much more we can tweak and improve. This is the bare minimum to get you going with Typescript on Neovim.&lt;&#x2F;p&gt;
&lt;p&gt;Next, let&#x27;s dig a little deeper on Tsserver CoC extension and some other cool Neovim plugins!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Home Development Setup 2020 - Pandemic Edition</title>
        <published>2020-08-10T07:00:00+00:00</published>
        <updated>2020-08-10T07:00:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/home-office-development-setup-2020-pandemic-edition/"/>
        <id>https://www.theminimalistdeveloper.com/home-office-development-setup-2020-pandemic-edition/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/home-office-development-setup-2020-pandemic-edition/">&lt;p&gt;Ah, 2020, what a year! &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;COVID-19_pandemic&quot;&gt;Raging Covid-19 pandemic&lt;&#x2F;a&gt;, &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nationalgeographic.com&#x2F;animals&#x2F;2020&#x2F;05&#x2F;asian-giant-hornets-arrive-united-states&#x2F;&quot;&gt;killer wasps&lt;&#x2F;a&gt;, &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.theguardian.com&#x2F;world&#x2F;2019&#x2F;jul&#x2F;03&#x2F;jair-bolsonaro-brazil-first-six-months-right-dismayed&quot;&gt;Bolsonaro&lt;&#x2F;a&gt;, &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.theguardian.com&#x2F;world&#x2F;2020&#x2F;aug&#x2F;07&#x2F;german-nudist-chases-wild-boar-that-stole-laptop-berlin-teufelssee&quot;&gt;a family of wild boars stealing notebooks from naked middle-aged men&lt;&#x2F;a&gt;, &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.bbc.com&#x2F;news&#x2F;world-asia-china-53325988&quot;&gt;bubonic plague&lt;&#x2F;a&gt;, whatever your wildest nightmares can request, 2020 can deliver.&lt;&#x2F;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;&#x2F;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;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.theminimalistdeveloper.com&#x2F;home-office-development-setup-2020-pandemic-edition&#x2F;.&#x2F;workstation-front-view.jpg&quot; alt=&quot;Workstation front view&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-desk&quot;&gt;The Desk&lt;&#x2F;h2&gt;
&lt;p&gt;Everything starts with the desk. It&#x27;s the foundation of the workspace.&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;I chose a kitchen tabletop from Ikea called &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ikea.com&#x2F;de&#x2F;de&#x2F;p&#x2F;karlby-arbeitsplatte-nussbaum-furnier-00335201&#x2F;?gclsrc=aw.ds&amp;amp;&amp;amp;gclid=Cj0KCQjwp4j6BRCRARIsAGq4yMHkc4JDwWY7jsKfalllCGMTYE89g20YfpkTQUdA9hyBpxRb2HLdpJAaAiAYEALw_wcB&quot;&gt;KARLBY&lt;&#x2F;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;&#x2F;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 class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ikea.com&#x2F;de&#x2F;de&#x2F;p&#x2F;alex-schubladenelement-schwarzbraun-40342285&#x2F;&quot;&gt;ALEX drawer&lt;&#x2F;a&gt; (also from Ikea) in the middle, and voilá: We had a desk.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.theminimalistdeveloper.com&#x2F;home-office-development-setup-2020-pandemic-edition&#x2F;.&#x2F;workstation-side-view.jpg&quot; alt=&quot;Workstation side view&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;computers&quot;&gt;Computers&lt;&#x2F;h2&gt;
&lt;p&gt;Currently, I have two computers in use. There is also an ancient Macbook Pro 13&quot; from 2012, which I am planning to repurpose as a Linux machine for development. But that&#x27;s a topic for another post.&lt;&#x2F;p&gt;
&lt;p&gt;The main machine is a Macbook Pro 15&quot; 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 class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.twelvesouth.com&#x2F;products&#x2F;bookarc-macbook?variant=31443535724601&quot;&gt;BookArc&lt;&#x2F;a&gt; alluminum support from Twelve south.&lt;&#x2F;p&gt;
&lt;p&gt;My personal computer at the moment is an AMD desktop (Windows&#x2F;Manjaro dual boot) that I&#x27;ve built end of last year, A.K.A Doom Eternal machine because that&#x27;s all I have been doing on that computer since March.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;monitors&quot;&gt;Monitors&lt;&#x2F;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;&#x2F;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 class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;instagram.com&#x2F;the.minimalist.developer&quot;&gt;@the.minimalist.developer&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now I am back to the basics, 90% of the time using only a single &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.samsung.com&#x2F;uk&#x2F;monitors&#x2F;uhd-ue570&#x2F;&quot;&gt;4k 28&quot; Samsung U28E590&lt;&#x2F;a&gt; hooked to a monitor arm I&#x27;ve found on Amazon.&lt;&#x2F;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;&#x2F;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 class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;i3wm.org&#x2F;&quot;&gt;I3 desktop manager&lt;&#x2F;a&gt;. It allows me to organize the workspace much better, with a 28&quot; display, there is not much need for more space.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keyboard&quot;&gt;Keyboard&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Currently, I am using an &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;en.obins.net&#x2F;&quot;&gt;Anne Pro 2&lt;&#x2F;a&gt; (Gateron blues switches) with the notebook and a &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.vortexgear.tw&#x2F;vortex2_2.asp?kind=47&amp;amp;kind2=220&amp;amp;kind3=&amp;amp;kind4=1023&quot;&gt;Pok3r&lt;&#x2F;a&gt; (MX Clear switches) on the desktop.&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
&lt;h2 id=&quot;mouse&quot;&gt;Mouse&lt;&#x2F;h2&gt;
&lt;p&gt;Neglected and often forgotten, the mouse is only a central piece when I am playing, that&#x27;s when I use a &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.logitechg.com&#x2F;en-us&#x2F;products&#x2F;gaming-mice&#x2F;g305-lightspeed-wireless-gaming-mouse.910-005280.html&quot;&gt;Logitech G305&lt;&#x2F;a&gt;.&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;The amount of interactions left to the mouse is small, that&#x27;s why I never paid much attention to it. But after a lot of time using &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.apple.com&#x2F;shop&#x2F;product&#x2F;MLA02LL&#x2F;A&#x2F;magic-mouse-2-silver&quot;&gt;Apple&#x27;s Magic Mouse&lt;&#x2F;a&gt;, I decided to invest in a device focused on ergonomics, my wrist was killing me, even with relatively low usage.&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Ended up choosing a &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.kensington.com&#x2F;p&#x2F;products&#x2F;electronic-control-solutions&#x2F;trackball-products&#x2F;expert-mouse-wireless-trackball&#x2F;&quot;&gt;Kensington Expert Mouse&lt;&#x2F;a&gt;, and never looked back.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;headphones&quot;&gt;Headphones&lt;&#x2F;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;&#x2F;p&gt;
&lt;p&gt;Most of the time, I use &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.apple.com&#x2F;airpods-2nd-generation&#x2F;&quot;&gt;Apple&#x27;s Airpods&lt;&#x2F;a&gt;, which works great, except when you have a lot of stuff connected over Bluetooth. If that&#x27;s the case, you can face a lot of connectivity issues, like I have been facing ☹.&lt;&#x2F;p&gt;
&lt;p&gt;While playing or listening to music, I use the &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;north-america.beyerdynamic.com&#x2F;dt-150.html&quot;&gt;Beyerdynamic DT 150&lt;&#x2F;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 class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.fiio.com&#x2F;k3&quot;&gt;Fiio K3&lt;&#x2F;a&gt;, a headphone amplifier, and Digitial Audio Converter.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;chair&quot;&gt;Chair&lt;&#x2F;h2&gt;
&lt;p&gt;For budget reasons, I chose the &lt;a class=&quot;external-link&quot; rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ikea.com&#x2F;de&#x2F;de&#x2F;p&#x2F;jaervfjaellet-drehstuhl-gunnared-dunkelgrau-30363594&#x2F;&quot;&gt;JÄRVFJÄLLET&lt;&#x2F;a&gt; from IKEA. It is a good looking chair, but I don&#x27;t find it very comfortable, the neck&#x2F;head support feels weirdly positioned, the arms have no adjustments whatsoever, among other things.&lt;&#x2F;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;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;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;&#x2F;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;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>About me</title>
        <published>2020-08-07T07:00:00+00:00</published>
        <updated>2020-08-07T07:00:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/about/"/>
        <id>https://www.theminimalistdeveloper.com/about/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/about/">&lt;h1 id=&quot;about-me&quot;&gt;About Me&lt;&#x2F;h1&gt;
&lt;p&gt;Hey there! My name is Rafael and I&#x27;m a tech enthusiast with a knack for building cool stuff and leading teams to do the same. I&#x27;ve been around the block for a while, building serverless setups to sleek web experiences. On this blog, I spill the beans on my adventures in tech, share tips on staying productive on the terminal, and talk about my love for minimalism.&lt;&#x2F;p&gt;
&lt;p&gt;Whether you&#x27;re a coder, a manager, or just someone looking to make tech work for you, stick around for a good laugh and some solid advice.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Hello World, Again...</title>
        <published>2020-08-07T07:00:00+00:00</published>
        <updated>2020-08-07T07:00:00+00:00</updated>
        
        <author>
          <name>
            
              Rafael Dias
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.theminimalistdeveloper.com/hello-world-again/"/>
        <id>https://www.theminimalistdeveloper.com/hello-world-again/</id>
        
        <content type="html" xml:base="https://www.theminimalistdeveloper.com/hello-world-again/">&lt;p&gt;Hello, world! My name is Rafael Dias, I am a Brasilian self-taught software engineer currently working at picture-perfect Munich, Germany, it is a great pleasure to have you here!&lt;&#x2F;p&gt;
&lt;p&gt;Here I will talk about software development, career, technology, gadgets, all geek-related stuff, you get the drill.&lt;&#x2F;p&gt;
&lt;p&gt;But before we begin, I know what you are thinking...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;another-blog-why&quot;&gt;Another blog? Why?!&lt;&#x2F;h2&gt;
&lt;p&gt;Oh God, yet another blog, why? Don&#x27;t we have billions of blogs already? Why bother to create another one?&lt;&#x2F;p&gt;
&lt;p&gt;Those are the questions I posed to myself over and over again, maybe the good old habit of self-sabotage playing its role, or just common sense trying to do its job, who knows?&lt;&#x2F;p&gt;
&lt;p&gt;After much deliberation on the subject, I understood the reasons that make sense for me to create yet another blog, to be honest, there are four very compelling ones:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-it-helps-me-to-learn-new-things&quot;&gt;1 - It helps me to learn new things&lt;&#x2F;h3&gt;
&lt;p&gt;There is no better way to ensure you know something than trying to explain to others.
In the process of explaining a complex topic, I found myself digging deeper and solidifying fundamental knowledge that has been proved invaluable in my day-to-day work.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-improves-my-communication-skills&quot;&gt;2 - Improves my communication skills&lt;&#x2F;h3&gt;
&lt;p&gt;It should be no secret by now that one of the most crucial, yet most often neglected, skill to a developer is communication. Being able to convey complex and abstract ideas in a simple and accessible way is priceless.
And writing is one of the best exercises for me.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-showcase-my-interests-and-skills&quot;&gt;3 - Showcase my interests and skills&lt;&#x2F;h3&gt;
&lt;p&gt;It is not an easy task to showcase your interests and skills, especially if you are mainly working with systems architecture and backend development like in my case.
So breaking down personal projects and ideas helps to lay out what interests me, my way of thinking, and my skills.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;4-the-possibility-of-helping-others&quot;&gt;4 - The possibility of helping others&lt;&#x2F;h3&gt;
&lt;p&gt;The gratifying feeling of helping someone to solve an irritating problem, or to understand new paradigms, or technologies is unparalleled to me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;and-where-does-the-newborn-go-from-here-the-net-is-vast-and-infinite&quot;&gt;And where does the newborn go from here? The net is vast and infinite&lt;&#x2F;h2&gt;
&lt;p&gt;Indeed the topics are endless, so much stuff to talk about so little time!
That&#x27;s why I will try to focus on serverless solutions, systems architectures, and productivity, which currently are my favorite topics to think and talk about, so expect the majority of the content to be about those things.&lt;&#x2F;p&gt;
&lt;p&gt;Even though I have failed miserably several times before when trying to keep a schedule on content, I will try to keep at least two posts a month.&lt;&#x2F;p&gt;
&lt;p&gt;So, I hope to see you back here soon!&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
