<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: iwaduarte</title>
    <description>The latest articles on DEV Community by iwaduarte (@iwaduarte).</description>
    <link>https://dev.to/iwaduarte</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F119786%2F554c79e3-487c-450d-b17e-3b2ad957d9c5.jpeg</url>
      <title>DEV Community: iwaduarte</title>
      <link>https://dev.to/iwaduarte</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iwaduarte"/>
    <language>en</language>
    <item>
      <title>Creating a blog. A complete guide to move towards madness.</title>
      <dc:creator>iwaduarte</dc:creator>
      <pubDate>Mon, 25 Sep 2023 17:06:06 +0000</pubDate>
      <link>https://dev.to/iwaduarte/creating-a-blog-a-complete-guide-to-move-towards-madness-1kel</link>
      <guid>https://dev.to/iwaduarte/creating-a-blog-a-complete-guide-to-move-towards-madness-1kel</guid>
      <description>&lt;h3&gt;
  
  
  I was chilling...
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ItUv_Q8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://iwaduarte.dev/_astro/chilling.2dbce14d_Zv1vrt.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ItUv_Q8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://iwaduarte.dev/_astro/chilling.2dbce14d_Zv1vrt.webp" alt="" width="800" height="800"&gt;&lt;/a&gt;&lt;em&gt;That it is not me, but indeed is chilling on this paradisaical island (DALLE-2).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When I started creating my site, I had in mind two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I needed to show that I was capable of delivering good code and that I understood things at a high level ("senior").&lt;/li&gt;
&lt;li&gt;It had to be easy to develop the website, thus I could focus on coding, articles, and features.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These ideas were old (early 2018). Way older than the influx of new developers, COVID-19,  the IT crisis, and layoffs. I wanted to&lt;br&gt;
enter, &lt;strong&gt;at the time&lt;/strong&gt;, a very &lt;em&gt;competitive&lt;/em&gt; market: &lt;strong&gt;working remotely&lt;/strong&gt;. For that, I needed a stunning website. I did not do much&lt;br&gt;
at first, my first website was kind of ugly, it had no articles but a dummy bot that caught the attention of just one nice recruiter.&lt;/p&gt;

&lt;p&gt;Forward to 2022, I needed a better UX/UI and my &lt;a href="https://ntiuira.myportfolio.com/work"&gt;sister&lt;/a&gt; helped me create a design&lt;br&gt;
for me. One thing came to mind, where would I put my &lt;strong&gt;articles&lt;/strong&gt;? I wanted to write things, and make jokes, and make &lt;em&gt;my&lt;/em&gt; mistakes.&lt;/p&gt;

&lt;p&gt;One great platform was &lt;em&gt;Medium&lt;/em&gt;. Simple, I thought. I will just hyperlink everything to Medium and get some data from their API to&lt;br&gt;
display only the initial information on my site. The problem is. Medium is not that great, they make integrations look bad. They discontinued their API and made it&lt;br&gt;
hard to scrape as well. &lt;a href="https://medium.com/@cndro/how-to-get-data-from-medium-api-ca3b3a660a81"&gt;People&lt;/a&gt; &lt;a href="https://javascript.plainenglish.io/how-to-fetch-your-medium-articles-in-your-website-31b79df9377f"&gt;created&lt;/a&gt; &lt;a href="https://medium.com/geekculture/get-your-medium-stories-stats-from-command-line-in-json-format-b6c36e49f70a"&gt;tutorials&lt;/a&gt; on how to circumvent that. It is a pain to do it.&lt;/p&gt;

&lt;p&gt;I barely had any articles, and one solution worked if you had less than 10 posts. So I did that. Serverless in mind, I would create a lambda function&lt;br&gt;
that would grab the page, parse the data, and return a formatted object to the requester.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//articles.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;XMLParser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fast-xml-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;XMLParser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="na"&gt;isBase64Encoded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xmlData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://medium.com/feed/@iwaduarte`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;javascriptObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;javascriptObject&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;rss&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;guid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dc:creator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content:encoded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;partialContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;figure&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;figcaption&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;partialContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/.*src="&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;".*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;guid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That would work for months and I would be okay if Medium did not limit the number of posts to 10 and if I did not have&lt;br&gt;
errors when grabbing content because my regex was not properly set (no matter how I changed it).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Kje79O5G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://iwaduarte.dev/_astro/oldformat.8bb3c63f_guApF.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Kje79O5G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://iwaduarte.dev/_astro/oldformat.8bb3c63f_guApF.webp" alt="" width="800" height="563"&gt;&lt;/a&gt;&lt;em&gt;As you can see, the images are broken or incorrect, and only 7 articles are shown&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To make things worse other people's articles started to become blocked and not even clearing the cache would work anymore. They started&lt;br&gt;
limiting people. They started a massive enshitification through paywalls.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have not seen it I have also talked about that &lt;a href="https://iwaduarte.dev/blog/en/04-gpt-4-and-why-it-is-good)"&gt;here&lt;/a&gt;.&lt;br&gt;
In short, &lt;em&gt;enshitification&lt;/em&gt; is the act of making the services on the web worse over time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that started bothering me. I mean. I write on your platform, and you can not even give me the right to read articles?&lt;br&gt;
You do not even allow me to easily grab a few articles and post metadata to use on my site? You need therapy for your controlling issues mate.&lt;br&gt;
And I need to stay away from you (or at least partially).&lt;/p&gt;
&lt;h4&gt;
  
  
  I was chilling man, I swear...
&lt;/h4&gt;
&lt;h3&gt;
  
  
  Migrating to  Astro
&lt;/h3&gt;

&lt;p&gt;My site is mostly static. I was looking for a solution where I could start writing that involved the minimum changes possible.&lt;br&gt;
After lots of investigation it came down to &lt;strong&gt;Next.js&lt;/strong&gt; and &lt;strong&gt;Argo&lt;/strong&gt;. With Argo being the recommended choice for my use case.&lt;br&gt;
No need for server-side mambo jambo, and thousands of tools, just the simplicity out of the box. The plug-and-play approach.&lt;/p&gt;

&lt;p&gt;If you are already using CRA I recommend following these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Migrate to vite :
&lt;a href="https://www.robinwieruch.de/vite-create-react-app/"&gt;Migrate to Vite from Create React App&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Update to Astro:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  npm uninstall @vitejs/plugin-react
  npm &lt;span class="nb"&gt;install &lt;/span&gt;astro @astrojs/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Rename &lt;code&gt;vite.config.js&lt;/code&gt; to &lt;code&gt;astro.config.mjs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Inside &lt;code&gt;astro.config.js&lt;/code&gt; rename &lt;code&gt;import react from '@vitejs/plugin-react'&lt;/code&gt; to &lt;code&gt;import react from '@astrojs/mdx'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;package.json&lt;/code&gt; rename the &lt;code&gt;"scripts"&lt;/code&gt; properties commands from &lt;code&gt;vite&lt;/code&gt; to &lt;code&gt;astro&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a folder called &lt;code&gt;pages&lt;/code&gt; inside the root directory&lt;/li&gt;
&lt;li&gt;Create a file called &lt;code&gt;index.astro&lt;/code&gt; inside &lt;code&gt;pages&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Put the content of the index.html inside &lt;code&gt;index.astro&lt;/code&gt; and import your &lt;code&gt;App.jsx&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
// index.astro
import App from '../App.jsx';
import '../style.css';
---

&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8" /&amp;gt;
  &amp;lt;link rel="icon" type="image/png" href="/favicon.ico" /&amp;gt;
  &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1" /&amp;gt;
  &amp;lt;meta name="theme-color" content="#000000" /&amp;gt;
  &amp;lt;meta name="description" content="iwaduarte portfolio dev fullstack" /&amp;gt;
  &amp;lt;title&amp;gt;@iwaduarte&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;App client:only='react'/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;npm run dev&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If you are starting from scratch I recommend following the &lt;a href="https://docs.astro.build/en/getting-started/"&gt;Astro documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That should be sufficient to migrate or start your application. You are now using Astro as your framework. Astro uses the concept of micro-frontend and islands which means that you can use React, Svelte, and Astro combined without having to migrate anything.&lt;/p&gt;

&lt;p&gt;Concerning blogs, Astro uses &lt;a href="https://en.wikipedia.org/wiki/Markdown"&gt;markdown&lt;/a&gt; by default as an option to create your blog posts. It is an easy markup language for creating formatted text that is adopted across several websites, it is well-supported and can be converted to HTML, PDF, etc. Websites like GitHub (README.md) and Reddit support user-generated markdown content which makes its use more appealing.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating content with ASTRO
&lt;/h3&gt;

&lt;p&gt;Astro gives you a powerful way of setting up content. Which is the &lt;code&gt;content&lt;/code&gt; folder. It is that simple!&lt;br&gt;
The context folder will be important because will give you Astro APIs that allow you to grab info on your static files. Inside this &lt;code&gt;content&lt;/code&gt; folder you will have to put either valid .md (markdown) or .mdx files.&lt;/p&gt;

&lt;p&gt;These files will contain all your text. Let's set a very simple example so you can use it inside your platform:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;content&lt;/code&gt; folder inside the root folder.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;blog&lt;/code&gt; folder inside &lt;code&gt;content&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a file called &lt;code&gt;my-first-post.mdx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create the following
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
title: My first post
subtitle: Hey, hey, hey.
description: ""
tags:
- introduction
author: Yo
date: "Some date"
slug: /blog/my-first-post
---

Every programmer would be like:

It doesn't work... Why?
It works...? Why
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  The power of MD and MDX files
&lt;/h3&gt;

&lt;p&gt;With markdown files, you can write things like "###" and "[]()" and that will respectively stylize a header text and create a link. It is so intuitive that once you get the gist of it and set things up will be writing like&lt;br&gt;
Stephen King!! Maybe, not like him. But at least fast.&lt;/p&gt;

&lt;p&gt;Markdown does not support JavaScript by default. To solve that, and to add integration with &lt;code&gt;jsx&lt;/code&gt; mdx was created. You can use jsx combined with markdown. Which is great for framework components. You can extend mdx functionality with plugins. You can create content faster if use javascript only. I will show a great example later. For more info about mdx please check their amazing website: &lt;a href="https://mdxjs.com/docs/what-is-mdx/"&gt;https://mdxjs.com/docs/what-is-mdx/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Migrating articles from MEDIUM
&lt;/h3&gt;

&lt;p&gt;Now things start to get more serious. You have set up everything. Your migration to Astro works, and you need to import all your posts from Medium.&lt;br&gt;
This is a very delicate topic. I am sorry, but currently, it is not an easy task. It is a long process but with this guide, you will wish you could find me a buy me a coffee (I hate coffee, so I will pass).&lt;/p&gt;

&lt;p&gt;If you do not want to port your old posts because you are averse to long processes, you can start writing brand new from your new Astro application and keep the old posts as hyperlinks. I do recommend however that you grab a cup of coffee, tea, or chocolate and embark with me on this journey.&lt;/p&gt;

&lt;p&gt;We are going to use two packages: &lt;a href="https://github.com/miry/medup"&gt;miry/medup&lt;/a&gt; and &lt;a href="https://github.com/dtesler/medium-to-markdown"&gt;medium-to-markdown&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  miry/medup
&lt;/h2&gt;
&lt;h3&gt;
  
  
  macOS
&lt;/h3&gt;

&lt;p&gt;If you have a linux or macOs system the installation will be a breeze.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap miry/medup
brew &lt;span class="nb"&gt;install &lt;/span&gt;medup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Windows
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;For Windows is mandatory to use &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/install#upgrade-version-from-wsl-1-to-wsl-2"&gt;WSL&lt;/a&gt;. This package runs with the Crystal Language which is not fully supported in Windows.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Install WSL2 with Ubuntu on Windows
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open PowerShell as Administrator and run:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wsl &lt;span class="nt"&gt;--install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install Ubuntu from the Microsoft Store. You can find Ubuntu under the Linux section.&lt;/li&gt;
&lt;li&gt;Launch Ubuntu from the start menu. The first time you launch it, it will complete its installation and ask you to create a user and set a password.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Linux and Windows (WSL2 Ubuntu)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Before installing Homebrew, update and upgrade the Ubuntu packages by running the following commands:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install Homebrew by pasting the following command in your Ubuntu terminal:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
/bin/bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Setup Homebrew Environment Variables: After the installation, add Homebrew to your shell profile:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.profile
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;/home/linuxbrew/.linuxbrew/bin/brew shellenv&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install medup
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
brew tap miry/medup
brew &lt;span class="nb"&gt;install &lt;/span&gt;medup

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Usage:
&lt;/h3&gt;

&lt;p&gt;You have &lt;strong&gt;medup&lt;/strong&gt; installed now.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are going to grab all your articles in Medium using the command below. The USERNAME is the same as the one used on the url medium.com/@USERNAME
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;medup &lt;span class="nt"&gt;-u&lt;/span&gt; USERNAME &lt;span class="nt"&gt;-d&lt;/span&gt; posts/USERNAME &lt;span class="nt"&gt;--assets-images&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: If you are on &lt;strong&gt;Windows&lt;/strong&gt; and want to access the folder path you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;explorer.exe &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can grab all files and posts and move them to your &lt;code&gt;content/blog/&lt;/code&gt; folder previously set. This library is great at downloading formatted files but some errors could occur:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;does not give you the assets: you will have to manually download your images&lt;/li&gt;
&lt;li&gt;does not properly format bold text:  it will give spacing between bolding ** word** when it should be *&lt;em&gt;word&lt;/em&gt;*&lt;/li&gt;
&lt;li&gt;not downloading some articles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apart from that the files are almost properly formatted in Markdown, which gives you 90% of the job done.&lt;/p&gt;

&lt;p&gt;For the remaining articles (if for some reason they have not been downloaded) you will use the second library. It is way poorer implementation than the @medup one, but it will give you a markdown-ish file to work with. Hopefully, you will have a few files for using this library.&lt;/p&gt;

&lt;h2&gt;
  
  
  medium-to-markdown
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install npm if not already installed&lt;/li&gt;
&lt;li&gt;Clone the repo
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/dtesler/medium-to-markdown.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;medium-to-markdown&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;Run
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Individually find the article post URL and run the command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run convert https://medium.com/@USERNAME/article &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; article.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Move the files to the &lt;code&gt;content/blog/&lt;/code&gt; folder previously set.&lt;/li&gt;
&lt;li&gt;Rename the files to have small filenames, make it easy to type inside the browser (i.e. &lt;code&gt;06-08-2023-a-very-big-title-name.md&lt;/code&gt; =&amp;gt; &lt;code&gt;small-title.md&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In possession of your markdown files, you will have to fix the errors discussed above. That should take you a good chunk of your time if you have many files&lt;br&gt;
however if you have an IDE and know some regex like this one &lt;code&gt;(!\[(.+[\)\.]).+\.\w+\))&lt;/code&gt; things can go way easier. Just use that regex to match &lt;a href=""&gt;&lt;/a&gt; tags&lt;br&gt;
and use the power of capturing groups to replace things that you would need. And voilà, you are now a mass editor.&lt;br&gt;
Like I keep saying in most of my posts, I got your back mate.&lt;/p&gt;

&lt;p&gt;Once everything is properly formatted we can start displaying the posts on your platform.&lt;/p&gt;
&lt;h3&gt;
  
  
  Displaying my posts
&lt;/h3&gt;

&lt;p&gt;You will now dynamically set a router file to be able to display your posts from the content without having to manually&lt;br&gt;
create a file every time you create content. For that, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;blog&lt;/code&gt; folder inside pages&lt;/li&gt;
&lt;li&gt;Create a file called &lt;code&gt;[...slug].astro&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Inside that file put the following code
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
  const blogPosts = await getCollection('blog');
  return blogPosts.map(post =&amp;gt; ({
    params: { slug: post.slug.replace('/blog','') }, props: { post }}
  ));
}

const { post } = Astro.props;
const { Content } = await post.render();

---
&amp;lt;Content/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Return to your &lt;code&gt;content/blog&lt;/code&gt; files to have the following slug in the &lt;code&gt;frontmatter&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/blog/small-title&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;You can go to your browser and type &lt;a href="http://localhost:4321/blog/small-title"&gt;http://localhost:4321/blog/small-title&lt;/a&gt; and you should be able to see your blog post.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Embedding YouTube videos
&lt;/h3&gt;

&lt;p&gt;You may have noticed that some of the &lt;em&gt;YouTube&lt;/em&gt; videos and &lt;em&gt;Codepen&lt;/em&gt; links that were on your site are appearing as links or looking broken.&lt;br&gt;
Unfortunately, markdown does not support embedded links. The good news is that mdx with a little bit of configuration can make your site beautiful&lt;br&gt;
again without using complicated &lt;code&gt;JSX&lt;/code&gt; or any other configuration than a simple markdown.&lt;/p&gt;

&lt;p&gt;From now on all your files are going to be renamed to .mdx, or at least the ones that need videos on the page and other advanced integrations.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the &lt;code&gt;mdx&lt;/code&gt; integration and plugins
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @astrojs/mdx
npm &lt;span class="nb"&gt;install&lt;/span&gt; @remark-embedder/core @remark-embedder/transformer-oembed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Update the file &lt;code&gt;astro.config.mjs&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;astro/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@astrojs/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mdx&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@astrojs/mdx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fauxRemarkEmbedder&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@remark-embedder/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fauxOembedTransformer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@remark-embedder/transformer-oembed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;remarkEmbedder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fauxRemarkEmbedder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;oembedTransformer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fauxOembedTransformer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;

&lt;span class="c1"&gt;// &amp;lt;https://astro.build/config&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;integrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mdx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;remarkPlugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nx"&gt;remarkEmbedder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;transformers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;oembedTransformer&lt;/span&gt;&lt;span class="p"&gt;]}]]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;And that is it. To run a YouTube video you just need the YouTube link:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/dQw4w9WgXcQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tip: You need to style the iframe afterward for things like width, height, margin, etc.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🎉 Congrats 🎉🎉🥳
&lt;/h3&gt;

&lt;p&gt;Now you have migrated and set up a powerful static website. It is time for celebration. Go for a walk.&lt;br&gt;
Go kiss your wife and children. Play 15 minutes of chess or Dota2. Come back when you are fully recharged.&lt;br&gt;
We need a few more steps to be able to claim the full benefits of this solution.&lt;/p&gt;
&lt;h3&gt;
  
  
  Cross-posting and POSSE
&lt;/h3&gt;

&lt;p&gt;See I am not Kent C. Dodds or Dan Abramov. I am not popular. Medium however is a gigantic platform.&lt;br&gt;
They invest millions of dollars every year. They have engineers, marketers, salespeople, and a huge influx&lt;br&gt;
of website access.&lt;br&gt;
People like you and I can not compete with them, we also can not be too much dependent on their "misalignments"&lt;br&gt;
(thus the migration). We have to find a middle ground to get the most out of this relationship.&lt;/p&gt;

&lt;p&gt;With that idea in mind comes the term POSSE - Publish (on your) Own Site, Syndicate Elsewhere.&lt;br&gt;
It is a cool idea that I have found in several good articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nicolas-hoizey.com/articles/2017/11/09/medium-is-only-an-edge-server-of-your-posse-cdn-your-own-blog-is-the-origin/"&gt;Medium is only an edge server of your POSSE CDN, your own blog is the origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cmichel.io/how-to-crosspost-to-medium/"&gt;How to cross-post to Medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://illuminea.com/ultimate-guide-to-wp-medium/"&gt;The ultimate guide to cross-posting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codybontecou.com/programmatically-posting-to-your-favorite-blogs.html"&gt;Post to Dev, Hashnode, and Medium using their APIs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will use their reach and they will use our text for a win-win situation.&lt;/p&gt;

&lt;p&gt;For posting things in an easy way I literally had to stop writing this article to help with a tool that does most of the job but it is kind of broken.&lt;br&gt;
Yeah yeah. I know. We have been there before. But not this time mate. This time I have taken the time and made some pull requests that I&lt;br&gt;
expect to be integrated into their package.&lt;/p&gt;

&lt;p&gt;Actually, forget about the PR request. I have created a way better library for that. It is called &lt;a href="https://www.npmjs.com/package/crossposting"&gt;crossposting&lt;/a&gt;&lt;br&gt;
it solves the problem of POSSE for you, and it is better than the others (seriously, I have spent one week just writing that). It allows you to publish to 3 main sites:&lt;br&gt;
dev.to, hashnode, and medium.&lt;/p&gt;

&lt;p&gt;For installation execute the following:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now you are going to configure the platforms by setting their individual keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# [platform]: dev | hashnode | medium&lt;/span&gt;
cpt setk &lt;span class="o"&gt;[&lt;/span&gt;platform]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to find the tokens/API keys of each platform you intend to cross-posting. The repository has a nice tutorial&lt;br&gt;
&lt;a href="https://github.com/iwaduarte/cross-post/blob/master/README.md#configure-authorization"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once everything is configured is time to use the tool to crosspost and profit. Navigate to the blog folder that we have set and&lt;br&gt;
execute the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cpt &amp;lt;url|path&amp;gt; &lt;span class="nt"&gt;-p&lt;/span&gt; dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;path&lt;/code&gt; is the name of your blog article if you are publishing from a local file and &lt;code&gt;url&lt;/code&gt; if your article is already posted on some website.&lt;br&gt;
In my case I have a local file with frontmatter metadata, which would be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cpt ./08-creating-a-blog.mdx &lt;span class="nt"&gt;-p&lt;/span&gt; dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Nice!
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lg5WKsVnEA4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nice :P&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If everything goes well. You should see your post on dev.to with &lt;strong&gt;&lt;em&gt;images set and ready to go&lt;/em&gt;&lt;/strong&gt;. The post is set for draft but when you start&lt;br&gt;
using the tool you can confidently publish directly to the platform, you can even add to your integration deployment (ci/cd) tool.&lt;br&gt;
Again, &lt;a href="https://github.com/iwaduarte/cross-post/blob/master/README.md"&gt;check the documentation&lt;/a&gt; it is easy to follow.&lt;/p&gt;

&lt;p&gt;So that is it. Once more, I hope I have brought you a little bit of happiness. This is a very thorough article, I believe. If you have any doubts or suggestions, please let me know so I can help you with it.&lt;br&gt;
If you think that this is amazing please leave a like, a comment, or just ignore it with love.&lt;/p&gt;

&lt;p&gt;Cheers mate.&lt;/p&gt;

</description>
      <category>astro</category>
      <category>blog</category>
      <category>markdown</category>
      <category>react</category>
    </item>
    <item>
      <title>Node creator says you should strive for simplicity.</title>
      <dc:creator>iwaduarte</dc:creator>
      <pubDate>Fri, 22 Sep 2023 05:43:25 +0000</pubDate>
      <link>https://dev.to/iwaduarte/node-creator-says-you-should-strive-for-simplicity-4j28</link>
      <guid>https://dev.to/iwaduarte/node-creator-says-you-should-strive-for-simplicity-4j28</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yM2tC9NM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AdLRyt-BrPS2WgUaTl2_DSQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yM2tC9NM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AdLRyt-BrPS2WgUaTl2_DSQ.png" alt="A frustrated user. (DALLE-2)" width="800" height="800"&gt;&lt;/a&gt;&lt;em&gt;A frustrated user. (DALLE-2)&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;&lt;em&gt;I hate almost all software&lt;/em&gt;&lt;/strong&gt;
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s unnecessary and complicated at almost every layer. At best I can congratulate someone for quickly and simply solving a problem on top of the shit that they are given. The only software that I like is one that I can easily understand and solves my problems. The amount of complexity I’m willing to tolerate is proportional to the size of the problem being solved. (Ryan Dahl)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://tinyclouds.org/rant"&gt;https://tinyclouds.org/rant&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>rant</category>
      <category>unix</category>
    </item>
    <item>
      <title>Stop the noise.</title>
      <dc:creator>iwaduarte</dc:creator>
      <pubDate>Fri, 22 Sep 2023 05:39:37 +0000</pubDate>
      <link>https://dev.to/iwaduarte/stop-the-noise-gcp</link>
      <guid>https://dev.to/iwaduarte/stop-the-noise-gcp</guid>
      <description>&lt;p&gt;With all this knowledge on the internet, people should cut the crap out of it when creating videos. There is too much bloated information already.&lt;/p&gt;

&lt;p&gt;That way, when creating videos, please aim to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Topics in description&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Less prolix approach (less talk and more action!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Less self-promoting (although is hard)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deeper topics if possible.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And now I am creating rules, right? Yep. Let’s forget that this post is an utterly nonsense bullshit rant for a moment and appreciate a world where information is good, non-biased, and straightforward.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/rBrd_3VMC3c"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8eM5D8hb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AhWCWmfObN5eK6hjJgoIdgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8eM5D8hb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AhWCWmfObN5eK6hjJgoIdgw.png" alt="wonderful world" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>youtube</category>
      <category>english</category>
      <category>content</category>
    </item>
    <item>
      <title>[AWS] Using API Gateway for S3 Uploads to Trigger Lambda Functions</title>
      <dc:creator>iwaduarte</dc:creator>
      <pubDate>Fri, 22 Sep 2023 05:33:20 +0000</pubDate>
      <link>https://dev.to/iwaduarte/aws-using-api-gateway-for-s3-uploads-to-trigger-lambda-functions-2edg</link>
      <guid>https://dev.to/iwaduarte/aws-using-api-gateway-for-s3-uploads-to-trigger-lambda-functions-2edg</guid>
      <description>&lt;p&gt;I have stated a few posts back that I would make a tutorial like that. And yet due to procrastination, I did not do it. Also, there are a lot of tutorials on the internet that &lt;em&gt;try&lt;/em&gt; to achieve the same thing.&lt;/p&gt;

&lt;p&gt;And that conflicts with my statement of no bullshit, no copy/pasta, direct-to-the-point mottos. When I had the idea to create this tutorial it was years ago. I had researched extensively to create a test framework for a company for which I was a consultant.&lt;/p&gt;

&lt;p&gt;At the time, serverless was being born, and not many tutorials or tools were available. I had to resort to the few that were there and a lot of sweat and pain through the hell which is the AWS documentation.&lt;/p&gt;

&lt;p&gt;I got to a pretty decent solution and thought: "Awesome if I could share this, someone would expend less time and I would win hearts in my goal of conquering and destroying worlds". Epic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f0tQ3Cwr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1200/format:webp/1%2AxoMn_6ya52svpYzin1qUPA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f0tQ3Cwr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1200/format:webp/1%2AxoMn_6ya52svpYzin1qUPA.jpeg" alt="https://makeameme.org/meme/planning-world-domination-418f014b3d" width="600" height="397"&gt;&lt;/a&gt; &lt;em&gt;(&lt;a href="https://makeameme.org/meme/planning-world-domination-418f014b3d"&gt;https://makeameme.org/meme/planning-world-domination-418f014b3d&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Nowadays we have chatGPT which gives you half-terrible answers to some topics and very good ones to others. Now serverless has been elevated and bashed.&lt;/p&gt;

&lt;p&gt;For that reason, a tutorial in the old format would be pointless. Thus, I will try to come up with a revision of other tutorials and add my flavor to it.&lt;/p&gt;

&lt;p&gt;Let's begin with our architecture. I want to send images to &lt;strong&gt;S3&lt;/strong&gt; using only &lt;strong&gt;AWS API Gateway&lt;/strong&gt; as a proxy. These &lt;strong&gt;images&lt;/strong&gt; once there will be &lt;strong&gt;checked for dimensions&lt;/strong&gt;, &lt;strong&gt;resized&lt;/strong&gt; if larger than &lt;strong&gt;1024x1024&lt;/strong&gt;, and if its &lt;strong&gt;size&lt;/strong&gt; is bigger than 5MB &lt;strong&gt;deleted&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--07g1r6c2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AxSyaDY15HD4XSZRxk5-k6A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--07g1r6c2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AxSyaDY15HD4XSZRxk5-k6A.png" alt="app.cloudcraft.co" width="800" height="450"&gt;&lt;/a&gt; &lt;em&gt;Our intended architecture ( app.cloudcraft.co )&lt;/em&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Why use API Gateway as a proxy instead of using lambda?
&lt;/h3&gt;

&lt;p&gt;Someone created a tutorial at:&lt;br&gt;&lt;br&gt;
&lt;a href="https://lumigo.io/blog/the-why-when-and-how-of-api-gateway-service-proxies/"&gt;https://lumigo.io/blog/the-why-when-and-how-of-api-gateway-service-proxies/&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For the lazy ones:&lt;br&gt;&lt;br&gt;
"&lt;strong&gt;Cold starts&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
...However, some applications have more strict latency requirements. Or maybe if the API is part of a call chain that involves multiple Lambda functions. In which case the cold starts can stack up and become problematic as a whole, even if individually they're fine."&lt;br&gt;&lt;br&gt;
"&lt;strong&gt;Cost&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Having a Lambda function in the mix means you also have to pay for the Lambda invocations as well as associated costs such as CloudWatch Logs."&lt;br&gt;&lt;br&gt;
"&lt;strong&gt;Limits&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Lambda also has two concurrency limits. ThereΓÇÖs the total number of concurrent executions of ALL functions in the region."&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(extracted from lumigo.io)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I would add other points here. &lt;strong&gt;Simplicity&lt;/strong&gt;. Less maintenance. Configure and forget. Powerful scaling solution.&lt;/p&gt;

&lt;p&gt;For our use case, we are going to use the &lt;a href="https://www.serverless.com/framework/docs/getting-started"&gt;Serverless Framework&lt;/a&gt; to speed things up.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Create a folder called &lt;strong&gt;&lt;code&gt;upload-s3&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; Go to your &lt;strong&gt;&lt;code&gt;terminal&lt;/code&gt;&lt;/strong&gt;. Navigate to the folder created.&lt;/li&gt;
&lt;li&gt; Install these dependencies on your project:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;  
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; serverless   
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; serverless-apigateway-service-proxy serverless-domain-manager 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Create a &lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt; file inside the folder with a few variables that will help set your AWS services upon deployment.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;CUSTOM_DOMAIN=images.yourdomain.com&lt;/span&gt;  
&lt;span class="s"&gt;CERTIFICATE_ARN=arn:aws:acm:region:account-id:certificate/certificate-id&lt;/span&gt;  
&lt;span class="s"&gt;SECRET=DONOTDRINKTHEKOOLAID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Create a &lt;strong&gt;&lt;code&gt;serverless.yml&lt;/code&gt;&lt;/strong&gt; file:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Name of the service  &lt;/span&gt;
&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;upload-s3&lt;/span&gt;  
&lt;span class="c1"&gt;# Use environment variables from .env file  &lt;/span&gt;
&lt;span class="na"&gt;useDotenv&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;  
&lt;span class="c1"&gt;# Provider-specific configuration  &lt;/span&gt;
&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws&lt;/span&gt;  &lt;span class="c1"&gt;# Cloud provider  &lt;/span&gt;
  &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodejs18.x&lt;/span&gt;  &lt;span class="c1"&gt;# Runtime language and version  &lt;/span&gt;
  &lt;span class="c1"&gt;# Deployment stage (default to 'dev' if not specified)  &lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${env:stage, 'dev'}&lt;/span&gt;  
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;  &lt;span class="c1"&gt;# AWS region  &lt;/span&gt;
  &lt;span class="na"&gt;versionFunctions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;  
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="c1"&gt;# Environment variable for the S3 bucket name  &lt;/span&gt;
    &lt;span class="na"&gt;BUCKET_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:service}-apigateway-proxy&lt;/span&gt;  
    &lt;span class="na"&gt;SECRET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${env:SECRET}&lt;/span&gt;  
  &lt;span class="na"&gt;iamRoleStatements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow&lt;/span&gt;  
      &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;s3:*&lt;/span&gt;  
      &lt;span class="na"&gt;Resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;arn:aws:s3:::${self:provider.environment.BUCKET_NAME}&lt;/span&gt;  
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;arn:aws:s3:::${self:provider.environment.BUCKET_NAME}/*&lt;/span&gt;  
  &lt;span class="na"&gt;apiGateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;binaryMediaTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;image/png&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;image/jpg&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;image/jpeg&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;image/gif&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;image/x-icon&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;application/octet-stream&lt;/span&gt;  

&lt;span class="c1"&gt;# Lambda functions  &lt;/span&gt;
&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;jwtAuthorizer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;authorizer.jwtAuthorizer&lt;/span&gt;  &lt;span class="c1"&gt;# Path to the JWT authorizer function  &lt;/span&gt;

  &lt;span class="na"&gt;checkFileSize&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="c1"&gt;# Path to the function that checks file size  &lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;handler.checkFileSize&lt;/span&gt;  
    &lt;span class="c1"&gt;# Triggered when a new object is created in the S3 bucket  &lt;/span&gt;
    &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;s3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;bucket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:provider.environment.BUCKET_NAME}&lt;/span&gt;  &lt;span class="c1"&gt;# Reference to the S3 bucket created in Resources  &lt;/span&gt;
          &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3:ObjectCreated:*&lt;/span&gt;  
          &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;temp/&lt;/span&gt;  


&lt;span class="c1"&gt;# AWS CloudFormation Resources  &lt;/span&gt;
&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;Authorizer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::ApiGateway::Authorizer&lt;/span&gt;  
      &lt;span class="na"&gt;DependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;JwtAuthorizerLambdaFunction&lt;/span&gt;  
      &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;AuthorizerResultTtlInSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0&lt;/span&gt;  
        &lt;span class="na"&gt;IdentitySource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;method.request.header.Authorization&lt;/span&gt;  
        &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jwtAuthorizer&lt;/span&gt;  
        &lt;span class="na"&gt;RestApiId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ApiGatewayRestApi&lt;/span&gt;  
        &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TOKEN&lt;/span&gt;  
        &lt;span class="na"&gt;AuthorizerUri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="s"&gt;Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${JwtAuthorizerLambdaFunction.Arn}/invocations&lt;/span&gt;  
    &lt;span class="na"&gt;LambdaInvokePermission&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Lambda::Permission&lt;/span&gt;  
      &lt;span class="na"&gt;DependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;JwtAuthorizerLambdaFunction&lt;/span&gt;  
      &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;FunctionName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!GetAtt&lt;/span&gt; &lt;span class="s"&gt;JwtAuthorizerLambdaFunction.Arn&lt;/span&gt;  
        &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lambda:InvokeFunction&lt;/span&gt;  
        &lt;span class="na"&gt;Principal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apigateway.amazonaws.com&lt;/span&gt;  
        &lt;span class="na"&gt;SourceArn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="s"&gt;Fn::Sub: arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/*/*&lt;/span&gt;  

&lt;span class="c1"&gt;# Custom configurations  &lt;/span&gt;
&lt;span class="na"&gt;custom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;apiGatewayServiceProxies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;s3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/images&lt;/span&gt;  
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;post&lt;/span&gt;  
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PutObject&lt;/span&gt;  
        &lt;span class="na"&gt;bucket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:provider.environment.BUCKET_NAME}&lt;/span&gt;  
        &lt;span class="na"&gt;pathOverride&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temp/{object}'&lt;/span&gt;  
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;queryStringParam&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;filename&lt;/span&gt;  
        &lt;span class="na"&gt;cors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;  
        &lt;span class="na"&gt;authorizationType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CUSTOM&lt;/span&gt;  
        &lt;span class="na"&gt;authorizerId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Authorizer&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;  
        &lt;span class="na"&gt;requestParameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;integration.request.header.x-amz-acl'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;'private'"&lt;/span&gt;  


    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;s3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/images/{filename}&lt;/span&gt;  
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get&lt;/span&gt;  
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GetObject&lt;/span&gt;  
        &lt;span class="na"&gt;bucket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:provider.environment.BUCKET_NAME}&lt;/span&gt;  
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;pathParam&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;filename&lt;/span&gt;  
        &lt;span class="na"&gt;cors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;  
        &lt;span class="na"&gt;authorizationType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CUSTOM&lt;/span&gt;  
        &lt;span class="na"&gt;authorizerId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;Authorizer&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;  

  &lt;span class="c1"&gt;# Comment it out if you do not want a customized domain.  &lt;/span&gt;
  &lt;span class="na"&gt;customDomain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;domainName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${env:CUSTOM_DOMAIN}&lt;/span&gt;  &lt;span class="c1"&gt;# Custom domain from environment variable  &lt;/span&gt;
    &lt;span class="na"&gt;certificateArn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${env:CERTIFICATE_ARN}&lt;/span&gt;  &lt;span class="c1"&gt;# Certificate ARN from environment variable  &lt;/span&gt;
    &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:provider.stage}&lt;/span&gt;  
    &lt;span class="na"&gt;createRoute53Record&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;  


&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless-apigateway-service-proxy&lt;/span&gt;  &lt;span class="c1"&gt;# Plugin to simplify API Gateway service proxy configurations  &lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless-domain-manager&lt;/span&gt; &lt;span class="c1"&gt;# Comment it out if you do not want a customized domain.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Run &lt;strong&gt;&lt;code&gt;serverless&lt;/code&gt;&lt;/strong&gt;:
You should have an &lt;strong&gt;AWS account&lt;/strong&gt; created. If not create it &lt;a href="https://portal.aws.amazon.com/billing/signup#/start/email"&gt;here&lt;/a&gt;. After that, create an &lt;strong&gt;IAM User&lt;/strong&gt; with permission to run your lambda and services. The configuration will be saved on your computer for future use.
&lt;em&gt;( If you already have an AWS account set and configured on your PC this part can be skipped.)&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w_bN-W2J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2A4zD5RsmjCQubosEAUCqJ7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w_bN-W2J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2A4zD5RsmjCQubosEAUCqJ7g.png" alt="" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the &lt;strong&gt;&lt;code&gt;authorizer.mjs&lt;/code&gt;&lt;/strong&gt; file and install its dependency:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;jsonwebtoken
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SECRET&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwtAuthorizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;authorizationToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;methodArn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorizationToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unauthorized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;principalId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;policyDocument&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2012-10-17&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;Statement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;  
        &lt;span class="p"&gt;{&lt;/span&gt;  
          &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;execute-api:Invoke&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;Effect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;methodArn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="p"&gt;},&lt;/span&gt;  
      &lt;span class="p"&gt;],&lt;/span&gt;  
    &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="p"&gt;};&lt;/span&gt;  
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Create the &lt;strong&gt;&lt;code&gt;handler.mjs&lt;/code&gt;&lt;/strong&gt; file and install its dependency:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;x64 &lt;span class="nt"&gt;--platform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux &lt;span class="nt"&gt;--libc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;glibc sharp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;HeadObjectCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;DeleteObjectCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;GetObjectCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;PutObjectCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/client-s3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sharp&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sharp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkFileSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;decodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\+&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
  &lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="p"&gt;};&lt;/span&gt;  

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ContentLength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ContentType&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;HeadObjectCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
  &lt;span class="p"&gt;);&lt;/span&gt;  

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ContentLength&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ContentLength&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DeleteObjectCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Deleted &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; as it was larger than 5MB`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Body&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;GetObjectCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BodyBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sharp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BodyBuffer&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;temp/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shouldResize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shouldResize&lt;/span&gt;  
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sharp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BodyBuffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
          &lt;span class="na"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inside&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;withoutEnlargement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="p"&gt;})&lt;/span&gt;  
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toBuffer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BodyBuffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

  &lt;span class="nx"&gt;shouldResize&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Resized &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;newKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Moved &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;newKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PutObjectCommand&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
      &lt;span class="na"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="nx"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="p"&gt;}),&lt;/span&gt;  
  &lt;span class="p"&gt;);&lt;/span&gt;  

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Deleted the original file &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DeleteObjectCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Serverless vs CloudFormation
&lt;/h3&gt;

&lt;p&gt;There are a lot of things happening above and we will touch on most points. If it is the first time you are dealing with serverless do not worry. If you are a more seasoned developer you can skip this part.&lt;/p&gt;

&lt;p&gt;The serverless framework is a way of automating the myriad of configurations that AWS requires you to do to create their services programmatically.&lt;/p&gt;

&lt;p&gt;There are a lot of ways of creating services via code with AWS. One of them is to use the CloudFormation service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Omppm_YUG2g"&gt;https://www.youtube.com/watch?v=Omppm_YUG2g&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the end, CloudFormation is just a YAML file with directives of what to create and how to create.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Import note:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Back then, &lt;a href="https://cloudncode.blog/2017/08/08/tidbit-api-gateway-as-a-s3-proxy-cloudformation-script-with-serverless-framework/"&gt;this main tutorial&lt;/a&gt; inspired me and used a full-fledged resources feature and no serverless plugins. Thankfully for us, the plugin s*&lt;em&gt;erverless-apigateway-service-proxy&lt;/em&gt;* is well-developed now and all boilerplate can be avoided. You can check the differences between our code and theirs by looking at this &lt;a href="https://github.com/maingi4/APIGatewayS3Proxy/blob/master/serverless.yml"&gt;repo&lt;/a&gt;:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The serverless framework helps you by creating a more simplified version of a CloudFormation.json file and other configurations that are handled for you. In the end, you will only need to type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;serverless deploy 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that will be it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going through the serverless.yml
&lt;/h2&gt;

&lt;p&gt;I have added comments on the &lt;em&gt;serverless.yaml&lt;/em&gt; file above but I want to touch on a few points:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iamRoleStatements&lt;/strong&gt;: Roles are temporary credentials that accounts or services can acquire. These roles let you manage/access/modify/listen to other services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;binaryMediaTypes&lt;/strong&gt;: Every request sent to API Gateway is by default treated as text. So it is important when sending binary data (images, audio, etc.) to specify the type to prevent unwanted coercion/parsing/encoding and therefore data corruption.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;functions&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Functions are the whole grail. There you add your code and forget about everything else (after the initial configuration) and that is serverless in a nutshell:&lt;br&gt;&lt;br&gt;
&lt;em&gt;"Forget about everything. Think about your logic and code, we handle the rest."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;jwtAuthorizer&lt;/strong&gt;: This function is responsible for making the endpoint &lt;strong&gt;secure&lt;/strong&gt;. Only authorized requests are allowed. This configuration is used in conjunction with the &lt;a href="https://github.com/serverless-operations/serverless-apigateway-service-proxy"&gt;serverless-apigateway-service-proxy&lt;/a&gt; plugin.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;checkFileSize&lt;/strong&gt;: This is the function of our logic. It is responsible for checking the file &lt;strong&gt;size&lt;/strong&gt; and deleting it in case surpasses our defined limit of 5MB and resizing images with dimensions higher than 1024x1024. I am using the package &lt;strong&gt;sharp&lt;/strong&gt; for that. As you can see I have defined directives when installing it which will ensure the binary for lambda is installed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;: This is the extra stuff and extra resources that you will add when the serverless framework and its plugins have failed you. It is here that you will define everything and it is pretty much copied to a CloudFront file without much alteration. For instance &lt;strong&gt;Authorizer: Type: AWS::ApiGateway::Authorizer&lt;/strong&gt; will create an authorization layer in AWS that connects API Gateway to our function to ensure proper access. You can see all types of resources/services &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;custom&lt;/strong&gt;: Here is where the pluginΓÇÖs configurations are defined. AWS is a monster with 200+ services and even the Serverless Framework can not cater to all types of needs and uses. Sometimes plugins are the best bet, sometimes we need to create everything using resources. Sometimes we just cry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apiGatewayServiceProxies&lt;/strong&gt;: Our &lt;a href="https://github.com/serverless-operations/serverless-apigateway-service-proxy"&gt;serverless-apigateway-service-proxy&lt;/a&gt; plugin&lt;br&gt;&lt;br&gt;
&lt;strong&gt;customDomain&lt;/strong&gt;: Our &lt;strong&gt;domain&lt;/strong&gt; plugin: &lt;a href="https://github.com/amplify-education/serverless-domain-manager"&gt;serverless-domain-manager&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Wait what? Domains? What is that?
&lt;/h3&gt;

&lt;p&gt;Domains are names (i.e. &lt;a href="http://www.google.com."&gt;www.google.com&lt;/a&gt;) that point to IP addresses. When the whole serverless stack is created the naming for accessing the API is something like this:&lt;br&gt;&lt;br&gt;
https://&lt;em&gt;&lt;code&gt;api-id&lt;/code&gt;&lt;/em&gt;.execute-api.&lt;em&gt;&lt;code&gt;region&lt;/code&gt;&lt;/em&gt;.amazonaws.com/&lt;em&gt;&lt;code&gt;stage&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This name can be customized with your own domain. LetΓÇÖs say you have bought your domain for your site and it is called: &lt;em&gt;coolpeopleneverdies.com&lt;/em&gt; and you like our whole application to update images to: &lt;em&gt;images.coolpeopleneverdies.com&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That is what the plugin is for. For managing and simplifying the &lt;em&gt;images.coolpeopleneverdies.com&lt;/em&gt; part. You do not want to send that ugly ass link to your friends to flex your skills with AWS. You would like to use the domain that you bought and it is beautiful.&lt;/p&gt;

&lt;p&gt;Before using that plugin you need to know that is &lt;strong&gt;mandatory (only if you want custom domains)&lt;/strong&gt; to buy and configure your domain, the certificates, and records.&lt;/p&gt;

&lt;p&gt;Here we have two nice tutorials on how to do it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Route53 (inside AWS)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.readysetcloud.io/blog/allen.helton/adding-a-custom-domain-to-aws-api-gateway/"&gt;https://www.readysetcloud.io/blog/allen.helton/adding-a-custom-domain-to-aws-api-gateway/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without Route53 (external domain registrar)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://medium.com/@sameera.godakanda/custom-domain-names-for-api-gw-e1deefe27ed"&gt;https://medium.com/@sameera.godakanda/custom-domain-names-for-api-gw-e1deefe27ed&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that, the &lt;code&gt;serverless.yaml&lt;/code&gt; file in our tutorial is configured for having the domain inside Route53 as well as its certificate (the first tutorial is the desired option). Also, there are manual parts in both tutorials above that are being automated here. So, skip those parts and follow the tutorial here instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If everything is looking complex already,&lt;/strong&gt; you can just disable the whole domain's shenanigans. I have placed comments on the serverless.yaml file on the lines you need to comment/delete so you can have your application and worry about that later. No big deal.&lt;/p&gt;

&lt;p&gt;If again, you already have your certificate set and it is using your domains in route 53 everything here will be a breeze.&lt;/p&gt;
&lt;h3&gt;
  
  
  Going through the .env
&lt;/h3&gt;

&lt;p&gt;The variables that you should set here are variables essential to your service to work. The variables set throughout the applications are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CUSTOM_DOMAIN&lt;/strong&gt;, &lt;strong&gt;CERTIFICATE_ARN,&lt;/strong&gt; and &lt;strong&gt;SECRET&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Make sure to populate these in your .env file.&lt;/p&gt;
&lt;h3&gt;
  
  
  How about our SECRET?
&lt;/h3&gt;

&lt;p&gt;We need these to make sure that our request is secure (authorized). I have decided to use JWT because it is simple to set up and is well-adopted for authorization.&lt;/p&gt;

&lt;p&gt;Our secret alone will not do it. It needs to be signed with a header and a payload ( that is how JWT works).&lt;/p&gt;

&lt;p&gt;Signing is like stamping a letter and saying and making sure that it will be recognized. We use cryptographic and shenanigans for that (HMAC if you are interested in the deep bottom of the sea)&lt;/p&gt;

&lt;p&gt;We would probably programmatically use a package to obtain the signed version providing only the &lt;strong&gt;SECRET.&lt;/strong&gt; However, in our case, and for simplicity we are going to use this &lt;a href="https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVzSW4iOiIxaCJ9.5vB8_F2mZ56Ix0IKmcffvbaHNtki-x063SRx8awsIAs"&gt;jwt.io&lt;/a&gt; website. You are going to find a &lt;strong&gt;VERIFY SIGNATURE&lt;/strong&gt; field, there you should add your &lt;strong&gt;SECRET&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
I have set a public payload with &lt;code&gt;“expires”: “1h”&lt;/code&gt; but you can add whatever you feel like.&lt;/p&gt;

&lt;p&gt;Copy the encoded result. That is what we are going to need to authorize our requests.&lt;/p&gt;
&lt;h3&gt;
  
  
  Finally…The magic is happening.
&lt;/h3&gt;

&lt;p&gt;After all this initial configuration you can run our final deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;serverless create_domain  
serverless deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will create everything for you. If you wanna see the magic happening apart from the serverless logs you should go to AWS &lt;a href="https://us-east-1.console.aws.amazon.com/cloudformation/"&gt;CloudFormation&lt;/a&gt;. There you will have detailed information about your stack recently created.&lt;/p&gt;

&lt;p&gt;After finishing we should start testing it. To make things more dynamic I have added a testing video.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=COOmY-tLESg"&gt;https://www.youtube.com/watch?v=COOmY-tLESg&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there you go. After watching this amazing scene you can see that &lt;em&gt;images.iwaduarte.dev&lt;/em&gt; is uploading and retrieving images from &lt;strong&gt;S3&lt;/strong&gt; and doing proper modifications (following our logic established at the beginning of the tutorial).&lt;/p&gt;

&lt;p&gt;I have also created a repository where you can check how the code integrates in case you feel like you cannot work it out from here.&lt;br&gt;&lt;br&gt;
You can access the repo &lt;a href="https://github.com/iwaduarte/tutorial-apigateway-s3-proxy"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Do not for one second think that this implementation was without hiccups.&lt;br&gt;&lt;br&gt;
I had to read and re-read the documentation on a few parts and tweak it here and there. So you are not alone if you want to customize something and you are not getting anywhere. Keep working my young one you will get there.&lt;/p&gt;

&lt;p&gt;Also, there are a lot of optimizations and things that could be added and I have skipped or ignored.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; For instance, I am installing binaries for &lt;strong&gt;sharp&lt;/strong&gt; for Linux although I am deploying inside a Windows machine. &lt;a href="https://sharp.pixelplumbing.com/install#cross-platform"&gt;https://sharp.pixelplumbing.com/install#cross-platform&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; I am not packaging individual functions
&lt;a href="https://www.serverless.com/framework/docs/providers/aws/guide/packaging#packaging-functions-separately"&gt;https://www.serverless.com/framework/docs/providers/aws/guide/packaging#packaging-functions-separately&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; I could have added layers &lt;a href="https://www.serverless.com/framework/docs/providers/aws/guide/layers"&gt;https://www.serverless.com/framework/docs/providers/aws/guide/layers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; I am not catering for local development
&lt;a href="https://www.serverless.com/plugins/serverless-offline"&gt;https://www.serverless.com/plugins/serverless-offline&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; I am not working with streams. I could be using the Readable Stream from the s3 GetObjectCommand, the problem is that would require much more configuration since it is very hard to use metadata and resize (sharp methods) and streams. The metadata function reads the entire stream so I may as well simplify my code considering the files are small. For more info, you can check this answer: &lt;a href="https://stackoverflow.com/a/66837302/7350853"&gt;https://stackoverflow.com/a/66837302/7350853&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; I particularly do not like the &lt;a href="https://github.com/amplify-education/serverless-domain-manager"&gt;&lt;strong&gt;domain manager&lt;/strong&gt;&lt;/a&gt;  approach, especially because it is a separate command with a lot of implications. I have set domain configuration only using resources and works better in my view. But I did not want to make things even more complicated for you.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Well, I did not want to create a book, and yet... here we are HAHAHAHAHAH. Thanks for getting here though. Hope this tutorial helps you become a better developer. Also, there are things you will need to figure out by yourself in case you need customization, that is the path mate. Embrace it. It is like life can be pretty easy sometimes and pretty intimidating too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1GTW-O1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AD-jwQm5W0t_B3QFSyv00dg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1GTW-O1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AD-jwQm5W0t_B3QFSyv00dg.jpeg" alt="https://www.amazon.com/Confucius-Philosophy-Demotivational-Sarcastic-Poster/dp/B08LF4JNX8?th=1" width="800" height="534"&gt;&lt;/a&gt; &lt;em&gt;(&lt;a href="https://www.amazon.com/Confucius-Philosophy-Demotivational-Sarcastic-Poster/dp/B08LF4JNX8?th=1"&gt;https://www.amazon.com/Confucius-Philosophy-Demotivational-Sarcastic-Poster/dp/B08LF4JNX8?th=1&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Before I become too philosophical leave a comment and I will answer as I feel like it. Cheers.&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>google</category>
      <category>extension</category>
      <category>javascript</category>
    </item>
    <item>
      <title>GPT 4 and Why it is Good for Chrome to Crumble</title>
      <dc:creator>iwaduarte</dc:creator>
      <pubDate>Fri, 22 Sep 2023 05:25:17 +0000</pubDate>
      <link>https://dev.to/iwaduarte/gpt-4-and-why-it-is-good-for-chrome-to-crumble-4bal</link>
      <guid>https://dev.to/iwaduarte/gpt-4-and-why-it-is-good-for-chrome-to-crumble-4bal</guid>
      <description>&lt;p&gt;A long time without writing. Yeah, in a world of noise, I do not want to be this prolific AI copy/pasta that we see everywhere. The goal is to be less lazy but still try to be original (try because the temptation is real). Every word from here is from my own troubled mind unless is corrected for mistakes (I use Grammarly or whatever is suited for that).&lt;/p&gt;

&lt;p&gt;I will introduce an extension today. It is called &lt;strong&gt;form-filler&lt;/strong&gt;. Basically, fill out forms. Nothing special, not intended for everyday use but for people looking for &lt;em&gt;jobs&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You could use it for anything if configured properly but that is not the idea. I’m unemployed right now, which totally sucks. But hey, I like building stuff. So why not waste my time crafting crap that no one in their right mind would want?&lt;/p&gt;

&lt;p&gt;Like the old adage: “Automate 1 minute worth of 2".&lt;/p&gt;

&lt;p&gt;My plan is simple: Fill forms faster, mass apply automatically, land thousands of interviews, and get rich quicker. Also, help anyone in the same situation.&lt;/p&gt;

&lt;p&gt;The uniqueness of form-filler is that without using any external service is capable of uploading &lt;strong&gt;PDF files&lt;/strong&gt;. The idea is to automate so you apply in sites like &lt;em&gt;greenhouse.io&lt;/em&gt;, &lt;em&gt;lever.co, workable.com&lt;/em&gt; and so many others without even having to click and select thousands of files by yourself. Trust me mate is pretty neat.&lt;/p&gt;

&lt;p&gt;Okay, great idea. Great time developing. Let’s input to &lt;em&gt;Chrome Web Store&lt;/em&gt; and be done with it. Wait a minute… Shhhhhiiiiii****t: They do not accept ManifestV2 for new extensions.&lt;/p&gt;

&lt;h1&gt;
  
  
  ManifestV2-V3-VX and why is that a problem?
&lt;/h1&gt;

&lt;p&gt;I think it happens to all companies. They start nice. They found a unique idea and/or they are better than everyone else. They say to the world: Don’t be evil. They actually mean it the first time.&lt;/p&gt;

&lt;p&gt;Everyone holds hands. It is like a scene from a Disney World movie with a rainbow at the end. Everyone is laughing. Popcorn, coke, pizza for everyone. Wow, what a dream company, what a future ahead of us.&lt;/p&gt;

&lt;p&gt;Money comes in.&lt;/p&gt;

&lt;p&gt;Pressure comes high. “Money” needs to be “escalated”. Don’t be evil they continue saying.&lt;/p&gt;

&lt;p&gt;More money. More investors. More bad decisions.&lt;/p&gt;

&lt;p&gt;A whole company culture can shift from making this world a nice one to:&lt;br&gt;
Q1 did not profit so we need to achieve profit in Q2, in order to improve and increase and escalate for Q3 and Q4.&lt;/p&gt;

&lt;p&gt;Elementary my dear reader, I am being simplistic. Of course, there are a lot of variables. But get this like a hyperbolic generalization of Google and its decisions over the years.&lt;/p&gt;

&lt;p&gt;From &lt;strong&gt;really cool&lt;/strong&gt; products and &lt;strong&gt;great vision&lt;/strong&gt; turned into &lt;em&gt;ash&lt;/em&gt; just because they did not earn enough or did not manage properly.&lt;br&gt;
&lt;a href="https://killedbygoogle.com/"&gt;https://killedbygoogle.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From &lt;strong&gt;features&lt;/strong&gt; in services that were &lt;strong&gt;free&lt;/strong&gt; and became &lt;strong&gt;ugly&lt;/strong&gt;, &lt;strong&gt;buggy&lt;/strong&gt;, and &lt;strong&gt;less appealing&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://www.androidpolice.com/2021/04/08/five-of-the-worst-things-google-has-ever-done/"&gt;https://www.androidpolice.com/2021/04/08/five-of-the-worst-things-google-has-ever-done/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://arstechnica.com/gadgets/2021/03/the-new-google-pay-repeats-all-the-same-mistakes-of-google-allo/"&gt;https://arstechnica.com/gadgets/2021/03/the-new-google-pay-repeats-all-the-same-mistakes-of-google-allo/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From &lt;strong&gt;features that did not have the user interest at hand but profit&lt;/strong&gt;. And I am talking about you &lt;a href="https://developer.chrome.com/docs/extensions/mv3/intro/"&gt;Manifest V3&lt;/a&gt;. You are a scam artist stunt that uses heavy words like &lt;strong&gt;security&lt;/strong&gt;, &lt;strong&gt;privacy&lt;/strong&gt;, and &lt;strong&gt;performance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p26turea--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://miro.medium.com/v2/resize:fit:596/1%2Aq_yR6Mn2dxwIPK6a0DPxuw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p26turea--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://miro.medium.com/v2/resize:fit:596/1%2Aq_yR6Mn2dxwIPK6a0DPxuw.gif" alt="Manifest V3 when Google is claiming its security" width="298" height="298"&gt;&lt;/a&gt;&lt;em&gt;Manifest V3 when Google is claiming its security&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I am not the only one claiming that. Hundreds of people are saying the same.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.eff.org/deeplinks/2021/12/chrome-users-beware-manifest-v3-deceitful-and-threatening"&gt;https://www.eff.org/deeplinks/2021/12/chrome-users-beware-manifest-v3-deceitful-and-threatening&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.reddit.com/r/chrome/comments/xijfgk/manifest_v3_is_bad_for_users/"&gt;https://www.reddit.com/r/chrome/comments/xijfgk/manifest_v3_is_bad_for_users/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://grantwinney.com/what-is-manifest-v3-and-why-is-google-pestering-me/"&gt;https://grantwinney.com/what-is-manifest-v3-and-why-is-google-pestering-me/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.techrepublic.com/article/google-makes-the-perfect-case-for-why-you-shouldnt-use-chrome/"&gt;https://www.techrepublic.com/article/google-makes-the-perfect-case-for-why-you-shouldnt-use-chrome/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.eff.org/deeplinks/2021/12/chrome-users-beware-manifest-v3-deceitful-and-threatening"&gt;https://www.eff.org/deeplinks/2021/12/chrome-users-beware-manifest-v3-deceitful-and-threatening&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem is that Google holds the majority of the market share when it comes to browsers(~62%). They can decide to ignore our complaints, after all, what can we do?&lt;/p&gt;

&lt;p&gt;Profit-first mentality means pushing the agenda without the user’s concern. It is not good for the community. But hey. It is cool. Just accept it already.&lt;/p&gt;

&lt;p&gt;If you are the bully in school, no one dares to stand up against you. And you call all the shots, right? Right?&lt;/p&gt;

&lt;h1&gt;
  
  
  The “Should be Open” company that is about gains too
&lt;/h1&gt;

&lt;p&gt;I could restart here, new company &lt;strong&gt;NON-profit&lt;/strong&gt;, make the world a better place, blah-blah-blah. &lt;br&gt;
Let’s create an &lt;strong&gt;Open A&lt;/strong&gt;rtificial &lt;strong&gt;I&lt;/strong&gt;ntelligence company blah-blah-blah. Nah mate we need to put food on the table. You know the gist.&lt;/p&gt;

&lt;p&gt;However, these guys opened the Pandora box. Sam Altman, Ilya Sutskeve (the main responsible for the ChatGPT code) and its engineering team were responsible for this revolution.&lt;/p&gt;

&lt;p&gt;And kudos to these guys. Amazing innovation. Great disruptive technology.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you lived under a rock and for some reason, you do not know what is chatGPT I will ask you to just come back to your rock. You have no quarrels here mate. Kidding. “Google” about it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea was so great that shook the entire industry. Now you have a digital handyman that you pay nothing and you take all the credits. Love it.&lt;br&gt;
Sign me up for it. And then millions did. Making the fastest-growing user base ever.&lt;/p&gt;

&lt;p&gt;That alerted the attention of big players. The Call-Me-Evil-I-Do-Not-Care guys (aka Microsoft) joined the battle and started heavily investing in these technologies. I mean who would not want it? This is truly great technology.&lt;/p&gt;

&lt;p&gt;And how the behemoth Google after being a prolific AI player did not have something similar?&lt;/p&gt;

&lt;p&gt;The problem with making big bugs mentality is that innovation goes against it. Since innovation sometimes loses big bucks for no return at all. After all, innovation is research, development, testing, failures, and is not cheap at all.&lt;br&gt;
We have seen before, thousands and thousands of companies that started to lose track even if did not look like it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Blockbuster Entertainment Inc., Xerox Holdings Corporation, Kodak, etc.&lt;br&gt;
&lt;a href="https://www.forbes.com/sites/biancamillercole/2019/01/10/innovate-or-die-how-a-lack-of-innovation-can-cause-business-failure/?sh=382b33af2fcb"&gt;https://www.forbes.com/sites/biancamillercole/2019/01/10/innovate-or-die-how-a-lack-of-innovation-can-cause-business-failure/?sh=382b33af2fcb&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So &lt;strong&gt;Microsoft&lt;/strong&gt; is amping the bets and &lt;strong&gt;Google&lt;/strong&gt; is trying to recover, &lt;strong&gt;Open.ai&lt;/strong&gt; is the new baby on the market. What does that have to do with ManifestV3?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A war is made of many battles, maybe when weak we need to retreat” — Cap. No One&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you are losing market. And the sentiment is that you are not cool anymore. When the youngest are shifting their habits. Sometimes you need to realize that being stubborn will not take you anywhere.&lt;/p&gt;

&lt;p&gt;And even if you are stubborn the new solutions that come with the new disruptive technology will embrace the neglected. In short, users will get heard eventually because that is the beauty of competition, I guess.&lt;/p&gt;

&lt;p&gt;Companies like &lt;strong&gt;Firefox&lt;/strong&gt; and others to come can grab a substantial part of the market share if played right. Google is losing battles and losing the market (albeit slowly). And this perception is crucial to make the right play.&lt;/p&gt;

&lt;p&gt;We all moved from Internet Explorer to Firefox and then to Google. Maybe is time to reverse shift and Google does not have any &lt;a href="https://www.semianalysis.com/p/google-we-have-no-moat-and-neither"&gt;&lt;strong&gt;moat&lt;/strong&gt;&lt;/a&gt; left.&lt;/p&gt;

&lt;h3&gt;
  
  
  A sad feeling that it is all for nothing
&lt;/h3&gt;

&lt;p&gt;Yep. So that is what I think will happen and that is why I am against Manifest V3 (those links are to be read Mr. Slacker). So I decided to not put my extension in the Google Web Store for the time being. However, I am aware that things can not go your way. And if I was great at predicting the market I would be rich (none is the case). Therefore, the feeling is just sadness.&lt;/p&gt;

&lt;p&gt;You can still use my &lt;strong&gt;form-filler&lt;/strong&gt; in Google though (Chromium-based browsers) and you can use it in &lt;strong&gt;Firefox&lt;/strong&gt; if you already made the change. Everything is further explained here:&lt;br&gt;
&lt;a href="https://github.com/iwaduarte/form-filler"&gt;https://github.com/iwaduarte/form-filler&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The worst part is that I have some ideas that could improve people’s daily lives and I could use the reach that Google has. But as the saying goes: If you can not win them, annoy them, criticize them, and then join them.&lt;br&gt;
“Don’t be hypocritical”.&lt;/p&gt;

&lt;p&gt;Also don’t get me wrong here. I do like money, a lot haha. It is not about margins or dividends but how you are smart about it. Google has amazing brain power. Every bright kid in the town (the world actually) wants to join it. But…politics, revenues, and short-sighted vision are making this ugly transition from the Google cool-kid to the Google bully-moronic and no one likes it.&lt;/p&gt;

&lt;p&gt;Please be cool. Always. The coolest. Me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SL8qqCvz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2Ak79dm9Wr6b7Oc_edwi5Rbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SL8qqCvz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2Ak79dm9Wr6b7Oc_edwi5Rbg.png" alt="Everything is so astonishing when you are cool. (DALLE-2)" width="800" height="800"&gt;&lt;/a&gt;&lt;em&gt;Everything is so astonishing when you are cool. (DALLE-2)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>google</category>
      <category>extension</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Applying laziness to the extreme: A new code generator for Node.js</title>
      <dc:creator>iwaduarte</dc:creator>
      <pubDate>Thu, 21 Sep 2023 16:33:15 +0000</pubDate>
      <link>https://dev.to/iwaduarte/applying-laziness-to-the-extreme-a-new-code-generator-for-nodejs-5406</link>
      <guid>https://dev.to/iwaduarte/applying-laziness-to-the-extreme-a-new-code-generator-for-nodejs-5406</guid>
      <description>&lt;p&gt;In my dev journey, I have always “clicked” the lazy button. Lazy is the way pretty much like &lt;a href="https://en.wikipedia.org/wiki/Dudeism"&gt;Dudeism&lt;/a&gt; is. Going with the flow and taking it easy until your boss is yelling at you about the bloody &lt;strong&gt;deadline&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instantly, you wake up and rush to do the things you are supposed to. You are running behind schedule and your panic button starts buzzing. “The new project”, they said. In an attempt to give yourself hope, you shake your head look at the clock, and think: “I am so fuck**d”.&lt;/p&gt;

&lt;p&gt;Fear not, my brave comrade. Here at Chaos Company Unlimited, we have your back.&lt;/p&gt;

&lt;p&gt;I present to you the short version of this tutorial &lt;strong&gt;(tl;dr)&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/express-sire"&gt;https://www.npmjs.com/package/express-sire&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go there, use it, and speed up the skeleton of your Node.js projects. Leave feedback, comments, and rages on the &lt;a href="https://github.com/iwaduarte/express-sire"&gt;GitHub page&lt;/a&gt; (or not, be your own master MUAHAHAHA).&lt;/p&gt;

&lt;h3&gt;
  
  
  The long story is also called:
&lt;/h3&gt;

&lt;h2&gt;
  
  
  The Wizard, The Revolutionist, and The Draughtsman
&lt;/h2&gt;

&lt;p&gt;When I was a baby…kidding.&lt;/p&gt;

&lt;p&gt;The year is 2009 and a mate called &lt;a href="https://en.wikipedia.org/wiki/Ryan_Dahl"&gt;Ryan&lt;/a&gt; is fed up with how JavaScript is being treated. A lot of bullies from their high-bloated OOP castles, throwing rocks and saying: “Java? — Script developers, please”. “Scum”. “Deserve to die, no less”&lt;/p&gt;

&lt;p&gt;They chant at all corners with a little sense of pride. Not anymore. A magician at Google is creating a powerful engine. In the distant future, that engine name will baptize cars.&lt;/p&gt;

&lt;p&gt;Ryan is young and naive and thinks all the time about revolutions. He hates complexity and bloated configurations. He heard that the wizard Lars Bak and his musketeers are making the potion engine available.&lt;/p&gt;

&lt;p&gt;Quickly, he grabs the engine papers and starts developing his revolution. With time and to his surprise, millions would join his cause and he would be responsible for creating a massive battalion. The Node battalion. Fuck***g Node.js. By many historians the greatest battalion of all time.&lt;/p&gt;

&lt;p&gt;In a tavern, a few hours from there a new designer for the black arts would have his moment to shine. He would join Ryan's army and help that naive crusade, he would be responsible for a decent part of Ryan’s battalion victories and fame.&lt;/p&gt;

&lt;p&gt;And his name: &lt;br&gt;
TJ Holowaychuk. (Pause here, I have to google every time to get this name right).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;They killed, cursed and left their battalion afterward, but that is not the point…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Node is the runtime that powers everything. And that is all matter for now… &lt;em&gt;(Deno and Bun are watching)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to TJ
&lt;/h2&gt;

&lt;p&gt;TJ created thousands of packages &lt;em&gt;(a “little” exaggeration to increase the narrative)&lt;/em&gt;, things like &lt;a href="https://expressjs.com/"&gt;express&lt;/a&gt;.js, &lt;a href="https://tj.github.io/commander.js/"&gt;commander&lt;/a&gt;.js, &lt;a href="https://stylus-lang.com/"&gt;stylus&lt;/a&gt;, &lt;a href="https://koajs.com/"&gt;koa&lt;/a&gt; so on and forth.&lt;/p&gt;

&lt;p&gt;The guy was so prolific that had people questioning if he was not a team instead of a person. He started as a designer with a level novice to become a one-of-a-kind developer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;That is the living proof that with dedication you can reach everything. (Bullshit. You cannot. But let’s give a hopeful vibe to that text).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our mate created our beloved &lt;a href="https://expressjs.com/en/starter/generator.html"&gt;express-generator&lt;/a&gt; as well. What does it? &lt;br&gt;
&lt;em&gt;(See? I told you cannot reach everything).&lt;/em&gt; It generates a web &lt;strong&gt;server with the express framework&lt;/strong&gt;. An easy and simple server created rapidly.&lt;/p&gt;

&lt;p&gt;Express-generator generates files for you. Generates a web server for you. It generates all the boilerplate code so you do not have to type and create files and configure everything from scratch.&lt;/p&gt;

&lt;p&gt;You can from there think about the logic. The business. The actual code. Instead of configuring things. It is simple enough that will not force you to write in a certain way or put through gigantic documentation so you can learn how to generate the “right way”. (Criticism intended)&lt;/p&gt;

&lt;p&gt;It is good because &lt;code&gt;express&lt;/code&gt; is good and simple. Therefore, it generates more of the simple. It is good for beginners and good for seasoned developers too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened then? Why did you create express-sire?
&lt;/h2&gt;

&lt;p&gt;I wanted to use a scaffold to increase my productivity. I want to be fast and lazy and the same time. Having configurations been done for me that I knew it would be the same for the thousandth time.&lt;/p&gt;

&lt;p&gt;I looked at the solutions out there. Like a true JavaScript developer, I did not like it. No. They are not worse than mine. They are probably way more complex than what I did and that is why I like what I have done even more.&lt;/p&gt;

&lt;p&gt;I have looked at &lt;a href="https://yeoman.io/"&gt;yeoman&lt;/a&gt; and the express ones out here and nothing met my criteria, which are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Be simple.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Up to date.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stupid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Did I say simple?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Oh, working like a lego block is a must too.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You would choose what you wanted to be installed. If you want it this way okay. If you wanted that way, okay. I want this with that and that. Okay got it.&lt;br&gt;
That is the whole idea. To provide a “click buttons generator that lets you choose what kind of delicious ingredients you want”&lt;/p&gt;

&lt;p&gt;And simple and stupid enough like express-generator. So, I went there for wisdom. Ohh boy. It gets interesting…&lt;/p&gt;

&lt;h2&gt;
  
  
  The steps in building
&lt;/h2&gt;

&lt;p&gt;The thing with &lt;code&gt;express-generator&lt;/code&gt; is that it is getting old. And &lt;code&gt;code&lt;/code&gt; gets old. It gets legacy. Because it is not as successful as it should &lt;strong&gt;9.000 weekly downloads&lt;/strong&gt; against &lt;strong&gt;21.000.000&lt;/strong&gt; (&lt;strong&gt;express&lt;/strong&gt;) it did not adhere to the current practices.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It still uses templating and pure/raw/old SSR&lt;/em&gt;. In an era of SPA, SSG, modern SSR, and micro-frontends the old way with templating is not as used anymore.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Still uses CJS (&lt;a href="https://en.wikipedia.org/wiki/CommonJS"&gt;CommonJS&lt;/a&gt;)&lt;/em&gt;. Node and packages are moving to &lt;a href="https://en.wikipedia.org/wiki/Embedded_System_Module"&gt;ESM&lt;/a&gt;. It is a messy and painful process but still, it is coming and nothing can prevent it. JavaScript language is evolving (for the best or worse) and new practices are being adopted every year.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It does not offer the lego block&lt;/em&gt;. It is minimalist and I love this simple tool. But I am greedy and lazy and want everything done by a computer so I can get the credit.&lt;/p&gt;

&lt;p&gt;With all that, I went and created a mutated version of this minimal tool.&lt;/p&gt;

&lt;p&gt;I wanted to create the same way express-generator did. It creates templates by delegating some “options” to a templating engine in this case &lt;strong&gt;EJS.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;EJS&lt;/strong&gt; is a simple templating language that lets you generate HTML markup with plain JavaScript. (&lt;a href="https://ejs.co/"&gt;&lt;strong&gt;source&lt;/strong&gt;&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A template file (app.js.ejs) inside the express-generator module would look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RBvPLp7D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2A4ZkOzaqVSVy1vPe1t_lpSA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RBvPLp7D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2A4ZkOzaqVSVy1vPe1t_lpSA.png" alt="ejs template" width="762" height="909"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although EJS is used to generate HTML files, the strategy here is to use the same templating but to build a .js file. An elegant and great solution at the time. Nowadays it seems off.&lt;/p&gt;

&lt;p&gt;EJS uses a method &lt;code&gt;render&lt;/code&gt; to render and parse and everything else and it is a big library. It uses a lot of &lt;a href="https://github.com/mde/ejs/blob/main/lib/utils.js"&gt;regex&lt;/a&gt; and functions and if and else's and it is a “complicated way” to create files. Especially in a world of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;Template Literals&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I am not saying that EJS is bad. Far from that. I am saying that for our task is overkill.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We did not need any of the above. JavaScript built-in feature would carry us away and deliver the message. The idea is to create a file from this powerful sorcery (template literals) and others had the same concept too (&lt;a href="https://github.com/postmanlabs/postman-code-generators/issues/516"&gt;here&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/graphql-tag"&gt;here,&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/@ahmadnassri/template-literals-engine"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;With template literals being the choice now we need to define how would be the best way of “parsing” the string template into an actual JavaScript object. Some strategies were thought of.&lt;/p&gt;

&lt;p&gt;First approach. Requiring the file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KUkH_9oS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2Anba8dzeP__nV8RWNUbhYkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KUkH_9oS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2Anba8dzeP__nV8RWNUbhYkw.png" alt="source: https://stackoverflow.com/a/42881547/7350853" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Second approach. Combining it with regex:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DsxDpFLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AqjoX--6C-YrhwXlPShpZHA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DsxDpFLZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AqjoX--6C-YrhwXlPShpZHA.png" alt="source: https://stackoverflow.com/a/71090080/7350853" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Third and final. Using eval:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PdwSlTtR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2A2ItnhNMWnWsVreK6CdfyIg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PdwSlTtR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2A2ItnhNMWnWsVreK6CdfyIg.png" alt="source: https://stackoverflow.com/a/55475107/7350853" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can guess. I choose eval. “Wait did you say eval?” Yep. Eval.&lt;br&gt;
“But..But.. Eval is E-V-I-L”. My comrade, avoid generalization and read the response above.&lt;/p&gt;

&lt;p&gt;I will make it clear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Although it can be dangerous to run JS code like this, if the templates are files that are in your control and written by you. I guess it can be done.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that is how I did. Apart from that, I found an awesome explanation from Safia Abdalla. She wrote a short but interesting text about how template literals work under the hood. I will not spoil it because it is easy to read and get the gist of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/captainsafia/how-do-template-literals-in-javascript-work-under-the-hood-4g2b"&gt;https://dev.to/captainsafia/how-do-template-literals-in-javascript-work-under-the-hood-4g2b&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay. Templates done. What else?&lt;/p&gt;

&lt;p&gt;We need to provide users with an interface, so they can install or provide commands inside a terminal. For that, I have tried to keep the minimum possible number of dependencies without having to reinvent the wheel. It is always the same approach: less work and simplicity, yielding big results.&lt;/p&gt;

&lt;p&gt;I have followed a few tutorials on the internet and I have read the express-generator codebase.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twilio.com/blog/how-to-build-a-cli-with-node-js"&gt;https://www.twilio.com/blog/how-to-build-a-cli-with-node-js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/henriquekuwai/criando-sua-cli-com-node-js-d6dee7d03110"&gt;https://medium.com/henriquekuwai/criando-sua-cli-com-node-js-d6dee7d03110&lt;/a&gt; (Portuguese)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.sitepoint.com/javascript-command-line-interface-cli-node-js/"&gt;https://www.sitepoint.com/javascript-command-line-interface-cli-node-js/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I did not follow their tutorial exactly but I got a good understanding of how it works and how it should work.&lt;/p&gt;

&lt;p&gt;I worked with these beautiful libraries myself (as you can see in the &lt;a href="https://github.com/iwaduarte/express-sire/blob/master/package.json"&gt;package.json&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/chalk/chalk#readme"&gt;Chalk&lt;/a&gt;: to have beautiful colors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/SBoudrias/Inquirer.js/#documentation"&gt;Inquirer&lt;/a&gt;: to ask questions to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/patorjk/figlet.js"&gt;Figlet&lt;/a&gt;: to have a badass ASCII lettering&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.npmjs.com/package/minimist"&gt;Minimist&lt;/a&gt;: to parse cli input arguments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have also tried to keep the package so low on new JavaScript features that Node users from v10 could adopt it and use it, but that did not work as expected and I had to revert to support Node v12.&lt;/p&gt;

&lt;p&gt;The package also installs things that I completely think are necessary but completely optional like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ESM Modules or CJS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/expressjs/compression"&gt;Compression&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/helmetjs/helmet"&gt;Helmet&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://sequelize.org/docs/v6/"&gt;Sequelize&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have made a few decisions related to adding &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt; as a default installation. Because it annoys me that people are still arguing over things that I think are &lt;a href="https://en.wikipedia.org/wiki/Law_of_triviality"&gt;bike-shedding&lt;/a&gt; and code formatting is one of them.&lt;/p&gt;

&lt;p&gt;All decisions apart I think this project is great and has a lot of paths to grow. I can (and will) implement more optional features so the user has everything it needs by lunch when the boss is yelling at the door and 15 minutes later, they are smiling with a project built to the awe of the audience.&lt;/p&gt;

&lt;p&gt;See? I told you I would get your back covered. Fear not mate. We are here for each other.&lt;/p&gt;

&lt;p&gt;Cheers.&lt;/p&gt;

&lt;h2&gt;
  
  
  More (external) reading:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://medium.com/blue-harvest-tech-blog/refining-efficient-approaches-to-build-reusable-templates-and-a-scaffold-for-the-application-f1459edc3f74"&gt;Efficient, reusable application templates and scaffolding&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.sitepoint.com/start-new-projects-faster/"&gt;Start New Projects Faster: 10 Scaffolding Web Dev Tools&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>express</category>
      <category>scaffold</category>
    </item>
    <item>
      <title>Simplicity vs Performance: How to transition between the background color and an image</title>
      <dc:creator>iwaduarte</dc:creator>
      <pubDate>Thu, 21 Sep 2023 16:14:25 +0000</pubDate>
      <link>https://dev.to/iwaduarte/simplicity-vs-performance-how-to-transition-between-the-background-color-and-an-image-o8l</link>
      <guid>https://dev.to/iwaduarte/simplicity-vs-performance-how-to-transition-between-the-background-color-and-an-image-o8l</guid>
      <description>&lt;p&gt;When developing my new website &lt;a href="https://iwaduarte.dev/"&gt;https://iwaduarte.dev/&lt;/a&gt; I wanted to have a “&lt;strong&gt;&lt;em&gt;killer”&lt;/em&gt;&lt;/strong&gt; feature: to hover over an element and have an image appear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HWViHWrB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AJtB-cYOYPAB8dK1Gu0MDxg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HWViHWrB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/1%2AJtB-cYOYPAB8dK1Gu0MDxg.gif" alt="I am cute, am I not?" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I didn’t know at the time, this apparently silly task would be a herculean one.&lt;/p&gt;

&lt;p&gt;The path of a developer is the one where none cares. You spend weeks trying to learn and circumvent a difficult obstacle in order to increase the quality of a feature. To fix a difficult bug. Increasing the performance of an animation to improve CPU and memory usage. Compressing everything with gzip to have your files served faster from the back end. Dropping requests from 1 second to 0.2s by refactoring the architecture or properly indexing the database.&lt;/p&gt;

&lt;p&gt;Does not matter, the result is always the same:&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;People do not care&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;How could they? They do not understand what task have you done or how long it took. How stressed you were or how hard you took on your shoulders. They did not experience it. They only saw the result and well: it looks okay but…&lt;/p&gt;

&lt;p&gt;Complex jobs are difficult to measure and appreciate. What was the last time you kissed your open-source Android phone thanking the gods of development for a such beautiful piece of art? &lt;br&gt;
Instead, you blamed the lags and silly configurations and everything else. And you are, my friend, a developer as well.&lt;/p&gt;

&lt;p&gt;If we do not get the effort and understand the intricacies of a task is hard to get the whole picture. That is why every profession will have a time where someone asks you to do: “a simple thing that will cost nothing of you”.&lt;/p&gt;

&lt;p&gt;For us are: “Could you build a better Medium/Instagram but with this better thing that I have thought of?”. For lawyers: “Could you listen to my sob story and offer free consultancy?”. For dentists: “Could look at my mouth and see why my teeth are so painful?”. Of course, the compensation is either minimal or non-existent.&lt;/p&gt;

&lt;p&gt;All these freebies requests and hard time measuring other people's worthiness are because people lack the understanding of how hard is to accrue that knowledge/skillset or how hard is to build those things and everything else related. They are blind. They are oblivious.&lt;/p&gt;

&lt;p&gt;For that reason, consider yourself as someone that should enlighten them and bring them closer to the problem. I promise they will pay attention if you deliver the bits and pieces as if they are a curious kid.&lt;/p&gt;

&lt;p&gt;With that, I will bring &lt;strong&gt;you&lt;/strong&gt; to &lt;strong&gt;the problem&lt;/strong&gt;. Maybe you did not know that &lt;strong&gt;we&lt;/strong&gt; had one.&lt;/p&gt;
&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;The objective is pretty simple, we hover over a background element and smoothly appear a beautiful image.&lt;/p&gt;

&lt;p&gt;Simple right?! Firstly you create a CSS like shown below adding the property on hover and the image. For smoothness, you would add the property &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transition"&gt;&lt;strong&gt;transition&lt;/strong&gt;&lt;/a&gt;. Yep. That &lt;strong&gt;does not work&lt;/strong&gt;. &lt;em&gt;(For more info on CSS transitions go &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions"&gt;here&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;codepen&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/iwaduarte/embed/qBYKXQP?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;That would be step 1.&lt;/p&gt;

&lt;p&gt;You could add &lt;code&gt;transition&lt;/code&gt; and try swapping &lt;strong&gt;&lt;code&gt;background&lt;/code&gt;&lt;/strong&gt; with &lt;strong&gt;&lt;code&gt;background-image&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;background-color&lt;/code&gt;&lt;/strong&gt;. Try using opacity and everything else. That would not work. &lt;em&gt;(You are welcome to try)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After a lot of attempts, you will either be frustrated and let it go or this absurd task or you would try to find a solution to understand why that bloody simple property is not giving you the expected results.&lt;/p&gt;

&lt;p&gt;After googling and reading, you discovered that the property &lt;code&gt;background-image&lt;/code&gt; is not &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties"&gt;animatable&lt;/a&gt;. Shockingly, &lt;code&gt;background&lt;/code&gt; it is though and you try clever different techniques to no avail as well. Life is hard you think.&lt;/p&gt;

&lt;p&gt;Those were the steps that I have done anyway. I have spent a few hours trying different approaches only to realize that 0 of them had any impact. Reading and trying answers from different sources on stack overflow did not make it either.&lt;/p&gt;

&lt;p&gt;I have learned that in relation to &lt;code&gt;transition&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;background-image&lt;/code&gt; to &lt;code&gt;background-image&lt;/code&gt;works in Chrome but does not work in &lt;strong&gt;Firefox. *(Google&lt;/strong&gt; is not following the standard).*&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;background-color&lt;/code&gt; to &lt;code&gt;background-color&lt;/code&gt; works just fine as the specs say.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;background&lt;/code&gt; &lt;em&gt;with a URL&lt;/em&gt; to &lt;code&gt;background-color&lt;/code&gt; does not respect the &lt;em&gt;&lt;code&gt;transition&lt;/code&gt;&lt;/em&gt; property although both of them are in the specs as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not even trying to set multiple backgrounds ( like &lt;code&gt;background: transparent, url(image.png)&lt;/code&gt;) by making one of them &lt;code&gt;transparent| rgba(X,Y,Z,0)&lt;/code&gt; would work because &lt;code&gt;color&lt;/code&gt; needs to be the last one as shown in the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Backgrounds_and_Borders/Using_multiple_backgrounds"&gt;MDN docs&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;codepen&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/iwaduarte/embed/LYmrzmM?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Therefore, you learned that you cannot easily use the property &lt;code&gt;transition&lt;/code&gt;with &lt;code&gt;background-image&lt;/code&gt;. Stupid as it is, you would have to navigate to the realm of hacks and tricks and that realm is far from simple.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hacks and tricks:
&lt;/h1&gt;

&lt;p&gt;The internet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/web-dev-survey-from-kyoto/change-the-background-color-with-transition-animation-web-dev-survey-from-kyoto-ef2f65756e9a"&gt;https://medium.com/web-dev-survey-from-kyoto/change-the-background-color-with-transition-animation-web-dev-survey-from-kyoto-ef2f65756e9a&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://coder-coder.com/background-image-opacity/"&gt;https://coder-coder.com/background-image-opacity/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/59599420/smooth-css-background-image-transition"&gt;https://stackoverflow.com/questions/59599420/smooth-css-background-image-transition&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/9483364/css3-background-image-transition"&gt;https://stackoverflow.com/questions/9483364/css3-background-image-transition&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/adriantwarog/tutorial-on-css-background-image-hovers-transitions-10cm"&gt;https://dev.to/adriantwarog/tutorial-on-css-background-image-hovers-transitions-10cm&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/42342419/css-transition-on-background-image-change-of-div"&gt;https://stackoverflow.com/questions/42342419/css-transition-on-background-image-change-of-div&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of the internet had the same ideas that appeared to me either too complicated or bloated.&lt;/p&gt;

&lt;p&gt;1 — Would have to set up a &lt;code&gt;position&lt;/code&gt; property that would create a new stack context (i.e &lt;code&gt;position: absolute, position: relative&lt;/code&gt; )&lt;/p&gt;

&lt;p&gt;2 — You would have to work with pseudo::elements and most of the tutorials were using either &lt;code&gt;::before&lt;/code&gt; or &lt;code&gt;::after&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;3 — After the elements were stacked we would make one of them disappear by using &lt;code&gt;transition&lt;/code&gt; property work with &lt;code&gt;opacity&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In my opinion, that would lead to a bloated solution, which made me furious. I spent so much time trying to write less code as possible and then for some reason I would have to circumvent this lack of implementation from the CSS &lt;a href="https://en.wikipedia.org/wiki/CSS_Working_Group"&gt;committee&lt;/a&gt; with that amount of code…Shame!Shame!&lt;/p&gt;

&lt;p&gt;I hated them for a brief period until I realized that in this story I am John Snow, do not know the whole picture and I am probably not bothered to investigate why the implementation was not done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eG8wVnS8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AXZxuCPKkFpw0Vy6S36hzZA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eG8wVnS8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AXZxuCPKkFpw0Vy6S36hzZA.png" alt="Ygritte yelling: “You know nothing John Snow” (DALLE-2)" width="800" height="800"&gt;&lt;/a&gt;&lt;em&gt;Ygritte yelling: “You know nothing John Snow” (DALLE-2)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Still as clueless as I am, I did not want to give up. Eventually, I would learn a different way, a simpler one. Keep digging, keep experimenting and you can achieve wonders I thought to myself.&lt;/p&gt;

&lt;p&gt;Happily, I came up with a different solution. That for me was simpler than the whole “junk” I found on the internet. “It is the best and I am the best”. “I am proud”. “I am a genius”. I know every developer can relate to these feelings.&lt;/p&gt;

&lt;p&gt;I have achieved the solution by using freaking &lt;code&gt;box-shadow&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;codepen&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/iwaduarte/embed/MWGXOvP?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow"&gt;&lt;strong&gt;Box-shadow&lt;/strong&gt;&lt;/a&gt; is a property that works by adding shadow to a box. As you know by now everything on an HTML page is a damn bloody box. This property has a &lt;code&gt;inset&lt;/code&gt; parameter that puts the shadow on top of the box instead of the corners.&lt;code&gt;box-shadow&lt;/code&gt; is also animatable and we could use it with the &lt;code&gt;transition&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Solved. “Genius”. “Geniality”. “Einstein”. I was like, mate you are a beast. THE GOOOOAAAT. You did what no one ever did. Let’s test with another browser and be done with it.&lt;/p&gt;

&lt;p&gt;And that is what I did. I made my ego so inflated by throwing nice compliments to myself that I forgot what is the drawbacks of this solution.&lt;/p&gt;

&lt;p&gt;And boy. I am dumb.&lt;/p&gt;

&lt;h1&gt;
  
  
  The dumb boy who cried drawbacks
&lt;/h1&gt;

&lt;p&gt;Firstly, there are concerns about animating &lt;code&gt;box-shadow&lt;/code&gt; , they are not performant. They do not scale.&lt;/p&gt;

&lt;p&gt;To understand that you should briefly know the CSS properties and browser animations.&lt;/p&gt;

&lt;p&gt;Modern browsers are like black boxes, most developers do not bother knowing (including myself) all the nitty-gritty details of it. Modern browsers are beasts, made from people way smarter than any of us.&lt;/p&gt;

&lt;p&gt;They are in the top 1%. They are the FANGers ( I will stop inventing words someday). And for that reason, we trust them blindly. The problem is they give us so many choices to work with and we end up doing the wrong approach, patting ourselves on the back and calling ourselves geniuses.&lt;/p&gt;

&lt;p&gt;In reality, you should go and understand the details or at least have a vague idea of what is what. And for animations you could start here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.dev/animations-overview/"&gt;Why are some animations slow?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In summary, there are phases when a browser is trying to display something on a webpage, they are called rendering pipelines. They have &lt;strong&gt;4 step&lt;/strong&gt;s: the first step (&lt;strong&gt;Style&lt;/strong&gt;) calls the second one (&lt;strong&gt;Layout&lt;/strong&gt;) which calls the third one (&lt;strong&gt;Paint&lt;/strong&gt;) which calls the last one (&lt;strong&gt;Composite&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;Think of CSS properties living in one of these realms. Some of them would demand the browser to do all of it over again (&lt;code&gt;box-shadow&lt;/code&gt;). Some will ask a lot less (&lt;code&gt;opacity&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Also, by searching about box-shadow performances I have found a few articles as well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://tobiasahlin.com/blog/how-to-animate-box-shadow/"&gt;https://tobiasahlin.com/blog/how-to-animate-box-shadow/&lt;/a&gt;&lt;br&gt;
How do you animate the &lt;code&gt;box-shadow&lt;/code&gt; property in CSS &lt;strong&gt;without&lt;/strong&gt; causing &lt;strong&gt;re-paints&lt;/strong&gt; on every frame, and heavily impacting the performance of your page? &lt;strong&gt;Short answer&lt;/strong&gt;: &lt;strong&gt;you don’t&lt;/strong&gt;. Animating a change of &lt;code&gt;box-shadow&lt;/code&gt; &lt;em&gt;will&lt;/em&gt; hurt performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.cloud66.com/box-shadow-transition-performance"&gt;https://blog.cloud66.com/box-shadow-transition-performance&lt;/a&gt;&lt;br&gt;
Adding a CSS transition to animate the &lt;code&gt;box-shadow&lt;/code&gt; of an element is a handy trick. It’s a design technique that’s often used on &lt;code&gt;hover&lt;/code&gt; to highlight something. If you've used this effect you might have noticed that sometimes the &lt;strong&gt;performance&lt;/strong&gt; can be &lt;strong&gt;sub optimal&lt;/strong&gt; making the animation slow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stop animating box-shadows the wrong way!&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=u6Rur7G8HNY"&gt;https://www.youtube.com/watch?v=u6Rur7G8HNY&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;All these articles/videos ask you to return to the very first solutions that we have encountered. They go to a detailed performance review as to why you shouldn’t use &lt;code&gt;box-shadow&lt;/code&gt; animations. They recommend the “bloated” but performant ones. What should we do now?&lt;/p&gt;

&lt;h1&gt;
  
  
  The clash between simplicity and performance. The last chapter.
&lt;/h1&gt;

&lt;p&gt;If you have read my previous articles, you would know that I am always striving for &lt;strong&gt;simplicity&lt;/strong&gt;. It is my motto and how I try to do things. Simplicity is also an abstract concept. Sometimes it can be perceived by one but not the other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt; is also my &lt;em&gt;baby&lt;/em&gt;. Why bother building something that doesn’t scale? That it is too costly because of that? The performance also indicates bad code, it is a metric that says: “Something is smelling funny here” or in other words, is a &lt;a href="https://en.wikipedia.org/wiki/Code_smell"&gt;code smell&lt;/a&gt; indicator.&lt;/p&gt;

&lt;p&gt;On these occasions that, to have one you have to let it go from the other, you have to ask yourself. Who is going to be hurt by that? Can I afford that?&lt;/p&gt;

&lt;p&gt;Let’s say I work for Canva &lt;em&gt;(&lt;a href="https://www.canva.com/en_au/"&gt;Canva&lt;/a&gt; is a web app tool for design)&lt;/em&gt;. And I am implementing this feature that is going to be used by millions. That I have to be performant otherwise I would end up losing customers, revenue, and money. And my work stability relies on that. You should come up with an answer here.&lt;/p&gt;

&lt;p&gt;But now let’s say that I have a solid team, working on a feature that will not be used by many. Mostly internally. Although the team is very great together it lacks the skills to code CSS because their background differs. Would you hurt some performance for a more readable code in this scenario?&lt;/p&gt;

&lt;p&gt;Now my scenario is that I have a website that few people would access and spend seconds on it. I have other things to do and I understand the drawbacks of my choice, should I change for performance? Should I stick with simplicity?&lt;/p&gt;

&lt;p&gt;Note that these answers are not definitive. Each one of you could get to a solid and different argument of why you would not do X or Y. It is not about who is right. The idea here is to understand and have solid reasons as to why you chose to hurt one for the other.&lt;/p&gt;

&lt;p&gt;Once we know the drawbacks of our choices, we expect that the decision will come easier. You would turn into a better developer and would grow to know that it is not always a &lt;em&gt;black-white decision&lt;/em&gt; but layers of &lt;strong&gt;geniality&lt;/strong&gt; and &lt;strong&gt;stupidity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So that is my take for you. Whatever you do, be bold and stupid, aim for the best out there (either simplicity or performance) and know your damn drawbacks.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>css</category>
      <category>performance</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Deployment (GitHub actions, Bitbucket pipelines), the stupid way</title>
      <dc:creator>iwaduarte</dc:creator>
      <pubDate>Thu, 21 Sep 2023 14:59:05 +0000</pubDate>
      <link>https://dev.to/iwaduarte/deployment-github-actions-bitbucket-pipelines-the-stupid-way-39f3</link>
      <guid>https://dev.to/iwaduarte/deployment-github-actions-bitbucket-pipelines-the-stupid-way-39f3</guid>
      <description>&lt;p&gt;Every now and then someone will come up with new words: DevOps, GitOps, *.(*.)Ops, CI/CD, multifactor deployment pods orchestrated in virtual containers (I think I have invented that one).&lt;/p&gt;

&lt;p&gt;Thing is, every single developer/team/company wants to achieve a simple objective. Have their files/product/”disruptive technologic” out there for the public to see. It is not always pretty though.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the best way of doing that?
&lt;/h2&gt;

&lt;p&gt;Let me dress my armor, my friend, I will start running from the best practice war before we dive into that topic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7G3nfM5B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2ARecgCXLkw5FFRcstzONpQQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7G3nfM5B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2ARecgCXLkw5FFRcstzONpQQ.png" alt="That is me, running from the war of best practices in my new shining armor. (DALLE-2)" width="800" height="800"&gt;&lt;/a&gt;&lt;em&gt;That is me, running from the war of best practices in my new shining armor. (DALLE-2)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;People are used to mixing the things that they know with the term &lt;em&gt;best practices&lt;/em&gt;. They learn something through sweat and tears and they hold to it. They hold to it even if there is better tech or way to do it out there, they hold to it because “it gets the job done”. They hold to it because they mastered it.&lt;/p&gt;

&lt;p&gt;It is okay. No problem with that. Learning something every second for the sake of learning is just terrible as well. No one should be forced to constantly learn. It is stressful and can get you a lot of headaches.&lt;/p&gt;

&lt;p&gt;The real problem is when you try to force on others your limitations or point of view as if they are the “right way of doing something” without a solid reason to do so and without having tried other alternatives and their pitfalls.&lt;/p&gt;

&lt;p&gt;For that reason, I want you to step back from your constructions and beliefs and bear with me for a second. If you do not like my suggestion you can always come back and read it again (hahaha) or stick with your position on the matter.&lt;/p&gt;

&lt;p&gt;Specifically, in terms of &lt;strong&gt;deploying&lt;/strong&gt; something, my opinion is that you should &lt;strong&gt;strive&lt;/strong&gt; for &lt;strong&gt;simplicity&lt;/strong&gt; and &lt;strong&gt;autonomy&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explaining the way codes are shipped in the most straightforward way
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;(You seasoned developer, can skip that part)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Currently, we have different ways of shipping code but mostly works in that way:&lt;/p&gt;

&lt;p&gt;Someone creates a code in their preferred programming language either by creating a new feature, editing existing functionality, or removing something. After that, they save what they did, and nowadays they use &lt;a href="https://en.wikipedia.org/wiki/Git"&gt;Git&lt;/a&gt; (VCS).&lt;/p&gt;

&lt;p&gt;After &lt;strong&gt;committing&lt;/strong&gt; the change, they usually &lt;strong&gt;push&lt;/strong&gt; their data to a specific hosted version control system (HVCS) that stores the code for team contribution/sharing. We can name a few:&lt;br&gt;
&lt;a href="https://about.gitlab.com/"&gt;GitLab&lt;/a&gt;, &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt;, &lt;a href="https://bitbucket.org/product"&gt;Bitbucket&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There they usually &lt;strong&gt;review&lt;/strong&gt; the code and diss the things that they do not like it. Through friendly or toxic comments, undisputed or heavy back-and-forth discussions they get to an agreement and the code can then move forward.&lt;/p&gt;

&lt;p&gt;Once the code is approved, it finally gets to the part for which this tutorial was created.&lt;/p&gt;

&lt;p&gt;Code is pushed and follows a specific &lt;strong&gt;YAML&lt;/strong&gt; file. It contains a set of &lt;strong&gt;rules&lt;/strong&gt; and commonly the goal is to connect to a specific &lt;strong&gt;&lt;em&gt;cloud service&lt;/em&gt;&lt;/strong&gt;, set arbitraries &lt;strong&gt;&lt;em&gt;environment variables&lt;/em&gt;&lt;/strong&gt;, and send the &lt;strong&gt;&lt;em&gt;code&lt;/em&gt;&lt;/strong&gt; their way.&lt;/p&gt;

&lt;p&gt;That is what the &lt;strong&gt;YAML&lt;/strong&gt; is for. Securely send data to a specific cloud service ( &lt;a href="https://aws.amazon.com/"&gt;AWS&lt;/a&gt;, &lt;a href="https://cloud.google.com/"&gt;Google Cloud&lt;/a&gt;, &lt;a href="https://azure.microsoft.com/en-us/"&gt;Azure&lt;/a&gt; ). They call the whole process, CI/CD, deployment, etc etc etc. (&lt;em&gt;Hey picky, I know they are not the same, but they kind of are.&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s3RZJBZ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AVICofDcune8ceAi41bJ0KQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s3RZJBZ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AVICofDcune8ceAi41bJ0KQ.png" alt="The picky guy staring at me and shaking his head (DALLE-2)" width="800" height="800"&gt;&lt;/a&gt;&lt;em&gt;The picky guy staring at me and shaking his head (DALLE-2)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If we could establish the steps of these files would be something like that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To connect and send data to the cloud service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Sometimes&lt;/em&gt; to do some testing and check some linting rules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To create the container image (as the container read it, a file with directives of what this “&lt;em&gt;mini-computer&lt;/em&gt;” should have installed and configurations) or bundle or whatever it needs to be transformed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To set up environment variables.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These 4 steps are not mandatory and by no means exhaustive either. They could appear isolated or in conjunction with the others. By looking at this you could think: “This should be straightforward work”.&lt;/p&gt;

&lt;p&gt;And yet people manage to make this &lt;strong&gt;YAML&lt;/strong&gt; file even more complex than needs to be.&lt;/p&gt;
&lt;h1&gt;
  
  
  The problem with too complex configuration files
&lt;/h1&gt;

&lt;p&gt;Let me start with examples, I will show you a few different files that are way too complex and a few that should be simple enough.&lt;/p&gt;
&lt;h3&gt;
  
  
  Show me the DAMN CODE!
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Sorry. It is my second post, I am striving for quality. :P&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This below would be one of the complex ones that could be simplified. &lt;em&gt;(It is tricky because **it looks&lt;/em&gt;* simple)*&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;someimage&lt;/span&gt;
&lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;master&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Prod&lt;/span&gt; 
          &lt;span class="c1"&gt;#deployment: production&lt;/span&gt;
          &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export AWS_ROLE="XXXXXXXXXXXXXXXX"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export AWS_ACCOUNT_NAME="XXXXXXXXXXXXXXXXXX"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export AWS_ACCOUNT_ID="XXXXXXXXXXXXXXXXXXXX"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export ENV="prod"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export timeStamp=$(date +%s)&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export DBHOST=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export LAMBDA_FN=YYYYYYYYYYYYYY&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;make deploy&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;I know you probably are wondering. What is the problem with that code and what does it do?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make yourself this question&lt;/strong&gt;. What is this configuration is intending to do? Remember my young Padawan, &lt;em&gt;“send some code to someplace”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Could you with that file alone see exactly what is going on here? See where is going? See which service is being called? Let me spoil for you, &lt;strong&gt;no you can not&lt;/strong&gt;. They are using &lt;a href="https://www.gnu.org/software/make/"&gt;MAKE&lt;/a&gt;, motherf*** &lt;a href="https://www.gnu.org/software/make/"&gt;MAKE&lt;/a&gt;. That is insane!&lt;/p&gt;

&lt;p&gt;I will show you &lt;strong&gt;&lt;em&gt;partially&lt;/em&gt;&lt;/strong&gt; what the command: make deploy is doing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;ifdef DOTENV&lt;/span&gt;
   &lt;span class="s"&gt;DOTENV_TARGET=dotenv&lt;/span&gt;
&lt;span class="s"&gt;else&lt;/span&gt;
   &lt;span class="s"&gt;DOTENV_TARGET=.env&lt;/span&gt;
&lt;span class="s"&gt;endif&lt;/span&gt;

&lt;span class="s"&gt;ifdef AWS_ROLE&lt;/span&gt;
  &lt;span class="s"&gt;ASSUME_REQUIRED?=assumeRole&lt;/span&gt;
&lt;span class="s"&gt;endif&lt;/span&gt;

&lt;span class="c1"&gt;################&lt;/span&gt;

&lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(ENV_RM_REQUIRED) $(DOTENV_TARGET) $(ASSUME_REQUIRED)&lt;/span&gt;
   &lt;span class="s"&gt;docker-compose run --rm serverless make _deps _buildLayer _deploy&lt;/span&gt;


&lt;span class="c1"&gt;# Create .env based on .env.template if .env does not exist&lt;/span&gt;
&lt;span class="na"&gt;.env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;XXXXXXXX&lt;/span&gt;

&lt;span class="c1"&gt;# Create/Overwrite .env with $(DOTENV)&lt;/span&gt;
&lt;span class="na"&gt;dotenv&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;YYYYYYYYYYYY&lt;/span&gt;

&lt;span class="na"&gt;_deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="s"&gt;echo "//registry.npmjs.org/:_authToken=$(NPM_TOKEN)" &amp;gt;&amp;gt; .npmrc&lt;/span&gt;
   &lt;span class="s"&gt;yarn config set registry http://registry.npmjs.org&lt;/span&gt;
   &lt;span class="s"&gt;yarn install --no-bin-links&lt;/span&gt;

&lt;span class="na"&gt;_buildLayer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="s"&gt;mkdir -p folder&lt;/span&gt;
   &lt;span class="s"&gt;mv database folder&lt;/span&gt;
   &lt;span class="s"&gt;mv node_modules folder&lt;/span&gt;
   &lt;span class="s"&gt;echo 'folder'&lt;/span&gt;
   &lt;span class="s"&gt;ls ./folder&lt;/span&gt;

&lt;span class="na"&gt;_deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="s"&gt;sls deploy --force -v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Could you make a guess what are they trying to do now? I will facilitate it for you:&lt;/p&gt;

&lt;p&gt;1 — Create env variables &lt;/p&gt;

&lt;p&gt;2 — Set registry for private package usage&lt;/p&gt;

&lt;p&gt;3 — Deploy using the serverless framework (&lt;strong&gt;sls deploy&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;4 —Setting everything through a docker container&lt;/p&gt;

&lt;p&gt;Serverless here is another beast and goes out of the scope of this tutorial. What I wanna show you is that they used MAKE to create the same things that you could achieve with the YAML file alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;But why did they do it?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The rationale behind this is to avoid &lt;a href="https://en.wikipedia.org/wiki/Vendor_lock-in"&gt;&lt;strong&gt;vendor locking&lt;/strong&gt;&lt;/a&gt; and to be &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Agnostic_(data)"&gt;agnostic-ready&lt;/a&gt;&lt;/strong&gt;. If they wanna move from &lt;strong&gt;Bitbucket&lt;/strong&gt; to &lt;strong&gt;GitLab&lt;/strong&gt; to &lt;strong&gt;GitWhatever&lt;/strong&gt; they would do it and the code would stay pretty much the same.&lt;/p&gt;

&lt;p&gt;These kinds of rationales are in my view overzealous. They show your ego side more than anything else. Yep, you know how to create performant pipelines with MAKE, you know your bits. You are competent. But still, you lack the simplification. The dumb-down approach that everyone is asking for.&lt;/p&gt;

&lt;p&gt;They are also too concerned with vendor locking. One way or another we are going to be vendor locked at something. Does not matter. Either AWS or Azure, GitLab or Git, &lt;em&gt;Java or Node.js&lt;/em&gt;. Therefore, trying to predict the future is not a great strategy in my books.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is worth noting that although programming languages are not vendors if you think indirectly they are. They are the first architectural decision that will base all your choices afterward.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agnostic approach or silver bullet approach which is worrying about changing lines of code in the future is not effective as well. How many times did you change your well-planned architecture? If everything runs well and you are not facing some significant cost/performance/errors issues you are probably giving that system a &lt;strong&gt;stamp&lt;/strong&gt; of the &lt;em&gt;legacy system to be&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Changing and breaking things are crucial parts of any human cycle. Do not be too concerned too soon. Wait until you get the problem… Capisci?&lt;/p&gt;

&lt;h2&gt;
  
  
  How I would change that for simplicity?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;someimage&lt;/span&gt;
&lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;master&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Prod&lt;/span&gt; 
          &lt;span class="c1"&gt;#deployment: production&lt;/span&gt;
          &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export AWS_ROLE="XXXXXXXXXXXXXXXX"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export AWS_ACCOUNT_NAME="XXXXXXXXXXXXXXXXXX"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export AWS_ACCOUNT_ID="XXXXXXXXXXXXXXXXXXXX"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export ENV="prod"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export timeStamp=$(date +%s)&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export DBHOST=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;export LAMBDA_FN=YYYYYYYYYYYYYY&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install serverless -g&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sls deploy --force -v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now look at that file and see exactly what is going to do. You do not need to iterate through thousands of files to get the gist of what is going on.&lt;br&gt;
It is &lt;strong&gt;easier&lt;/strong&gt;, it is &lt;strong&gt;simpler&lt;/strong&gt; and it is &lt;strong&gt;straightforward&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And with that comes the first suggestion. Try to put the &lt;strong&gt;minimum number of files out there&lt;/strong&gt;. In case you have 100000 lines of YAML file. Okay. You deserve a better organization but instead of organizing first assuming that your configuration will grow, embrace the chaos and let run wild for a while. You can thank me later.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem with environment variables
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Where to put my .env variables?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Firstly, what is env variables ? You can check this article &lt;a href="https://www.freecodecamp.org/news/what-are-environment-variables-and-how-can-i-use-them-with-gatsby-and-netlify/"&gt;https://www.freecodecamp.org/news/what-are-environment-variables-and-how-can-i-use-them-with-gatsby-and-netlify/&lt;/a&gt; (you can skip the gatsby and netlify part)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another current problem is related to where to store environment variables. People waste too many times arguing about where should be the safest place out there and they ended up doing the silliest things ever.&lt;/p&gt;

&lt;p&gt;I have seen companies store their environment variables in a database. Seriously.&lt;strong&gt;&lt;em&gt;IN A DATABASE&lt;/em&gt;&lt;/strong&gt;, in a &lt;strong&gt;TABLE&lt;/strong&gt;, plain &lt;strong&gt;ENGLISH,&lt;/strong&gt; and contained every single token/PWD/user to every service used inside their application. Please, do not do this. There is no rationale behind it, sometimes we do not know any better.&lt;/p&gt;

&lt;p&gt;The most common place is to use a file .&lt;strong&gt;env&lt;/strong&gt;. It has led to problems like people committing their &lt;a href="https://www.ndss-symposium.org/wp-content/uploads/2019/02/ndss2019_04B-3_Meli_paper.pdf"&gt;credentials to public repositories&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another way is to store the credentials in a &lt;strong&gt;secrets manager&lt;/strong&gt; in the cloud. &lt;br&gt;
From there your application asynchronously would request the credential when needed. For using ou would need to use their SDK. Here goes a simple example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/57618689/how-do-i-use-aws-secret-manager-with-nodejs-lambda/57618800#57618800"&gt;https://stackoverflow.com/questions/57618689/how-do-i-use-aws-secret-manager-with-nodejs-lambda/57618800#57618800&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more info, you can check this: &lt;a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html"&gt;using AWS SSM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Both of the solutions are fine. If you have configured your .env variables correctly they will be a strong candidate. The simplest, easiest, laziest way that I can think of is to combine .env files and the hosted version control system feature that allows saving encrypted secrets to be used in the deployment phase.&lt;/p&gt;

&lt;p&gt;GitHub calls it &lt;strong&gt;Action secrets&lt;/strong&gt;, Bitbucket calls it &lt;strong&gt;Repository variables.&lt;/strong&gt; If done right that will suffice for 90% of the cases.&lt;/p&gt;

&lt;p&gt;For GitHub you would go for that link:&lt;br&gt;
&lt;a href="https://github.com/iwaduarte/my-finances/settings/secrets/actions"&gt;https://github.com/your-username/your-repository/settings/secrets/actions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zIh9lFhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2ALKYEkX3xxT9ZOgqFpujqaQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zIh9lFhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2ALKYEkX3xxT9ZOgqFpujqaQ.png" alt="You can see that environment variables are encrypted as described in the image. (GitHub settings)" width="800" height="398"&gt;&lt;/a&gt;&lt;em&gt;You can see that environment variables are encrypted as described in the image. (GitHub settings)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For Bitbucket you would have:&lt;br&gt;
&lt;a href="https://bitbucket.org/iwaduarte/my-repo/admin/addon/admin/pipelines/repository-variables"&gt;https://bitbucket.org/your-username/your-repo/admin/addon/admin/pipelines/repository-variables&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ui928FL7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2A_1pwxy_guP95uNzU-Xcq4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ui928FL7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2A_1pwxy_guP95uNzU-Xcq4g.png" alt="In Bitbucket you can encrypt or not. Your choice." width="800" height="353"&gt;&lt;/a&gt;&lt;em&gt;In Bitbucket you can encrypt or not. Your choice.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And then you would configure your file as follows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bitbucket YAML:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;master&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test and deploy to dev&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:16&lt;/span&gt;
          &lt;span class="na"&gt;caches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node&lt;/span&gt;
          &lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
          &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install serverless -g&lt;/span&gt;
             &lt;span class="s"&gt;- serverless config credentials --provider aws --key $AWS_KEY --secret $AWS_SECRET&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;touch .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_NAME=$DB_NAME" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_USER=$DB_USER" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_DIALECT=$DB_DIALECT" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_PASS=$DEV_DB_PASS" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_HOST=$DEV_DB_HOST" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless deploy&lt;/span&gt;
          &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dist/**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Explained steps:&lt;/em&gt;&lt;br&gt;&lt;br&gt;
1— The variables $AWS_KEY and $AWS_SECRET are set in the &lt;strong&gt;repository variables&lt;/strong&gt; section (as explained above) and they are important to the serverless framework.&lt;/p&gt;

&lt;p&gt;2— Then we create a file .env with the command &lt;strong&gt;.touch env&lt;/strong&gt; and we start populating the secrets/variable in it (i.e “DB_NAME=$DB_NAME” &amp;gt;&amp;gt; .env )&lt;/p&gt;

&lt;p&gt;3 — This .env file will be sent with other files to the selected destination (in that case they will send environment variables to &lt;a href="https://aws.amazon.com/lambda/"&gt;AWS lambda&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub YAML:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Fargate&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Node to ECS Fargate&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;16.x&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2-beta&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;16'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set env variables&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;touch .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "NODE_ENV=stage" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
          &lt;span class="s"&gt;echo "SERVICE_NAME=${{ secrets.SERVICE_NAME_PROD }}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
          &lt;span class="s"&gt;echo "AWS_ACCESS_KEY=${{ secrets.AWS_ACCESS_KEY_ID}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "AWS_SECRET_ACCESS=${{ secrets.AWS_SECRET_ACCESS_KEY}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE=${{ secrets.DATABASE}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE_HOST=${{ secrets.DATABASE_HOST}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE_USER=${{ secrets.DATABASE_USER}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD}}" &amp;gt;&amp;gt; .env&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS credentials&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;aws-access-key-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_ACCESS_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-secret-access-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_SECRET_ACCESS_KEY}}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_REGION_ECS }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to Amazon ECR&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;login-ecr&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/amazon-ecr-login@v1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build, tag, and push image to Amazon ECR&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build-image&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ECR_REGISTRY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.login-ecr.outputs.registry }}&lt;/span&gt;
          &lt;span class="na"&gt;ECR_REPOSITORY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ECR_REPOSITORY }}&lt;/span&gt;
          &lt;span class="na"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.NODE_ENV }}-latest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;# Build a docker container and&lt;/span&gt;
          &lt;span class="s"&gt;# push it to ECR so that it can&lt;/span&gt;
          &lt;span class="s"&gt;# be deployed to ECS.&lt;/span&gt;
          &lt;span class="s"&gt;docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .&lt;/span&gt;
          &lt;span class="s"&gt;docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG&lt;/span&gt;
          &lt;span class="s"&gt;echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Fill in the new image ID in the Amazon ECS task definition&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;task-def&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/amazon-ecs-render-task-definition@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;task-definition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ecs-task-definition-${{ env.NODE_ENV }}.json&lt;/span&gt;
          &lt;span class="na"&gt;container-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;container-name&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.build-image.outputs.image }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Amazon ECS task definition&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/amazon-ecs-deploy-task-definition@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;task-definition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.task-def.outputs.task-definition }}&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.SERVICE_NAME }}&lt;/span&gt;
          &lt;span class="na"&gt;cluster&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ECS_CLUSTER_NAME }}&lt;/span&gt;
          &lt;span class="na"&gt;wait-for-service-stability&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS credentials&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;aws-access-key-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_ACCESS_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-secret-access-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_SECRET_ACCESS }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_REGION }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Explained steps:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1 — This is a little more convoluted example. It sends data to a service called &lt;a href="https://aws.amazon.com/fargate/getting-started/?nc=sn&amp;amp;loc=3"&gt;Fargate&lt;/a&gt; through a series of &lt;strong&gt;GitHub actions&lt;/strong&gt; from other repositories (official AWS ones)&lt;/p&gt;

&lt;p&gt;2 — It needs the environment variables that were set in the repository in &lt;strong&gt;Action secrets&lt;/strong&gt; (above).&lt;/p&gt;

&lt;p&gt;3 — It creates the .env file that will be saved inside that image that will run on Fargate&lt;/p&gt;

&lt;p&gt;4 — Not only uses the environment variables for creating the .env file but to connect to AWS services.&lt;/p&gt;

&lt;p&gt;This is a way more complex YAML file with several steps and configurations and yet it uses one file. If you read carefully you can see what is going to do, it uses the secrets from the VCS service and sends the code to the Fargate service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Straightforward, boring even.&lt;/strong&gt; And if you know a little about YAML configuration, you would say: “&lt;strong&gt;simple&lt;/strong&gt; to follow”. However, if you do not know what is all this jargon, fear not.&lt;/p&gt;

&lt;p&gt;They have provided beautiful documentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions"&gt;&lt;strong&gt;GitHub — Understanding GitHub actions&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://support.atlassian.com/bitbucket-cloud/docs/configure-bitbucket-pipelinesyml/"&gt;&lt;strong&gt;BitBucket — Configure bitbucket-pipelines.yml (same as YAML)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the last part of this tutorial let’s discuss when you have different branches and similar code for them.&lt;/p&gt;
&lt;h1&gt;
  
  
  The problem with having different branches and similar behavior
&lt;/h1&gt;
&lt;h3&gt;
  
  
  Run actions on specific branches
&lt;/h3&gt;

&lt;p&gt;For BitBucket, branches are part of the configuration, so you can set the specific branch and the configuration will run exclusively. That feature is &lt;strong&gt;very important (kudos to the Atlassian team)&lt;/strong&gt; because you can have a separate development branch and production in the same config file. Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and test&lt;/span&gt;
        &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;
  &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;master&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy  to PRODUCTION&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:16&lt;/span&gt;
          &lt;span class="na"&gt;caches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node&lt;/span&gt;
          &lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
          &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install serverless -g&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless config credentials --provider aws --key $AWS_KEY --secret $AWS_SECRET&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;touch .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_NAME=$DB_NAME_PROD" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_USER=$DB_USER_PROD" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_DIALECT=$DB_DIALECT_PROD" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_PASS=$DEV_DB_PASS_PROD" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_HOST=$DEV_DB_HOST_PROD" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless deploy&lt;/span&gt;
          &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dist/**&lt;/span&gt;
    &lt;span class="na"&gt;develop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy to DEVELOP&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:16&lt;/span&gt;
          &lt;span class="na"&gt;caches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node&lt;/span&gt;
          &lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
          &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install serverless -g&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless config credentials --provider aws --key $AWS_KEY --secret $AWS_SECRET&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;touch .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_NAME=$DB_NAME_DEV" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_USER=$DB_USER_DEV" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_DIALECT=$DB_DIALECT_DEV" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_PASS=$DEV_DB_PASS_DEV" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "DB_HOST=$DEV_DB_HOST_DEV" &amp;gt;&amp;gt; .env&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless deploy&lt;/span&gt;
          &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dist/**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In that case, if you push an application to the master branch only the master gets updated, and development is skipped. Pretty neat huh?&lt;/p&gt;

&lt;h2&gt;
  
  
  How about GitHub?
&lt;/h2&gt;

&lt;p&gt;I do not know why it is different. Many times in my journey I did not like how they made things and everything seemed more complicated. As you know by now I have aversion to cleverness when brings more stuff for me to learn/work.&lt;/p&gt;

&lt;p&gt;Some of the tutorials that I have read before coming up with my (rant) one are pretty good, except when it comes to branches:&lt;br&gt;
&lt;a href="https://keithweaverca.medium.com/only-run-github-actions-on-specific-branches-694782fcc07"&gt;https://keithweaverca.medium.com/only-run-github-actions-on-specific-branches-694782fcc07&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/sysf/how-to-set-up-github-workflows-and-create-github-actions-using-docker-3a5ba7ec0988"&gt;https://medium.com/sysf/how-to-set-up-github-workflows-and-create-github-actions-using-docker-3a5ba7ec0988&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They have the same strategy. If you create a branch you create a different file.And “new branch — new YAML” paradigm it goes against what I have defended here so far, do you remember my young Padawan?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Try to put the &lt;strong&gt;minimum number of files out there&lt;/strong&gt;.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And with that and the help of the best place to copypasta code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/a/58142412/7350853"&gt;https://stackoverflow.com/a/58142412/7350853&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After reading that you can see the solution. We could now come up with a better version. Using if’s. Simple if’s. Well known by every developer that has touched a surface of a keyboard. Great. Let’s do this.&lt;/p&gt;

&lt;p&gt;Reusing the same Fargate YAML file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Fargate&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Node to ECS Fargate&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;16.x&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2-beta&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;16'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set env variables for DEVELOP&lt;/span&gt;
      &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/develop'&lt;/span&gt;
        &lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;touch .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "NODE_ENV=dev" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
          &lt;span class="s"&gt;echo "SERVICE_NAME=${{ secrets.SERVICE_NAME_DEV }}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
          &lt;span class="s"&gt;echo "AWS_ACCESS_KEY=${{ secrets.AWS_ACCESS_KEY_ID}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "AWS_SECRET_ACCESS=${{ secrets.AWS_SECRET_ACCESS_KEY}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE=${{ secrets.DATABASE_DEV}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE_HOST=${{ secrets.DATABASE_HOST_DEV}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE_USER=${{ secrets.DATABASE_USER_DEV}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD_DEV}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set env variables for PRODUCTION&lt;/span&gt;
      &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/master'&lt;/span&gt;
        &lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;touch .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "NODE_ENV=dev" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
          &lt;span class="s"&gt;echo "SERVICE_NAME=${{ secrets.SERVICE_NAME_PROD }}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
          &lt;span class="s"&gt;echo "AWS_ACCESS_KEY=${{ secrets.AWS_ACCESS_KEY_ID}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "AWS_SECRET_ACCESS=${{ secrets.AWS_SECRET_ACCESS_KEY}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE=${{ secrets.DATABASE_DEV}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE_HOST=${{ secrets.DATABASE_HOST_PROD}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE_USER=${{ secrets.DATABASE_USER_PROD}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
          &lt;span class="s"&gt;echo "DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD_PROD}}" &amp;gt;&amp;gt; .env&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS credentials&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;aws-access-key-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_ACCESS_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-secret-access-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_SECRET_ACCESS_KEY}}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_REGION_ECS }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to Amazon ECR&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;login-ecr&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/amazon-ecr-login@v1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build, tag, and push image to Amazon ECR&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build-image&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ECR_REGISTRY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.login-ecr.outputs.registry }}&lt;/span&gt;
          &lt;span class="na"&gt;ECR_REPOSITORY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ECR_REPOSITORY }}&lt;/span&gt;
          &lt;span class="na"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.NODE_ENV }}-latest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;# Build a docker container and&lt;/span&gt;
          &lt;span class="s"&gt;# push it to ECR so that it can&lt;/span&gt;
          &lt;span class="s"&gt;# be deployed to ECS.&lt;/span&gt;
          &lt;span class="s"&gt;docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .&lt;/span&gt;
          &lt;span class="s"&gt;docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG&lt;/span&gt;
          &lt;span class="s"&gt;echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Fill in the new image ID in the Amazon ECS task definition&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;task-def&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/amazon-ecs-render-task-definition@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;task-definition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ecs-task-definition-${{ env.NODE_ENV }}.json&lt;/span&gt;
          &lt;span class="na"&gt;container-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;container-name&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.build-image.outputs.image }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Amazon ECS task definition&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/amazon-ecs-deploy-task-definition@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;task-definition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.task-def.outputs.task-definition }}&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.SERVICE_NAME }}&lt;/span&gt;
          &lt;span class="na"&gt;cluster&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ECS_CLUSTER_NAME }}&lt;/span&gt;
          &lt;span class="na"&gt;wait-for-service-stability&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS credentials&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;aws-access-key-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_ACCESS_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-secret-access-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_SECRET_ACCESS }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_REGION }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can easily see, using the IF clause ( if: github.ref == ‘branch' ) we have set the &lt;strong&gt;Actions secrets&lt;/strong&gt; for production and the &lt;strong&gt;Action secrets&lt;/strong&gt; for development and they will only populate the .env file when the specific branch is committed.&lt;/p&gt;

&lt;p&gt;That is the stupidest way ever and I am proud. It is so straightforward that you will not need MAKE or thousands of files or anything else. Just a little bit of if’s here and there, a few env variables set and there you go you are mastering the way of becoming a &lt;strong&gt;Jedi of KISS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LyfzlwHb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AJ6dVkeK5-slWJV55tpaDIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LyfzlwHb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AJ6dVkeK5-slWJV55tpaDIQ.png" alt="KISS (Keep it simple, stupid) (DALLE-2)" width="800" height="800"&gt;&lt;/a&gt;&lt;em&gt;KISS (Keep it simple, stupid) (DALLE-2)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is worth noting, that I know, the world is full of complicated cases and specific scenarios that would need some level of complexity. Most of your rationale defending your idea can indeed be the only and only solution. I will not dispute that, there are complex cases that I as a blub programmer will not even conceive in my limited perception/knowledge.&lt;/p&gt;

&lt;p&gt;And that is fine. I am aiming at the ones that do not have a clue of what they are doing or did not stop to think a little bit if that would bring joy a few weeks later when everyone forgets what they did.&lt;/p&gt;

&lt;p&gt;I am defending simplicity and autonomy. I could go and show several other cases and problematic approaches but I guess that I have delivered the message of how to be utmost sophisticated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finally&lt;/strong&gt; you can face them my young one. Without any hesitation or fear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PeXxW_-_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AXyl8tlFUu54asFbLcQOsvA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PeXxW_-_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1400/format:webp/1%2AXyl8tlFUu54asFbLcQOsvA.png" alt="My padawan is starting to believe. (DALLE-2)" width="800" height="800"&gt;&lt;/a&gt;&lt;em&gt;My padawan is starting to believe. (DALLE-2)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Good luck with your journey!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>github</category>
      <category>bitbucket</category>
    </item>
    <item>
      <title>A bad introduction. A poorly written saga. A virgin (not anymore).</title>
      <dc:creator>iwaduarte</dc:creator>
      <pubDate>Thu, 21 Sep 2023 10:35:30 +0000</pubDate>
      <link>https://dev.to/iwaduarte/a-bad-introduction-a-poorly-written-saga-a-virgin-not-anymore-115f</link>
      <guid>https://dev.to/iwaduarte/a-bad-introduction-a-poorly-written-saga-a-virgin-not-anymore-115f</guid>
      <description>&lt;p&gt;This will be a &lt;strong&gt;big fluffy post&lt;/strong&gt; for the rare times. To be honest I do not like it writing “that much”. However, in this special case, it is mandatory ( like losing my virginity was). It is full of mistakes, a lot of undesired attention, critics, and a lot of bad performance but in the end, we always remember it.&lt;/p&gt;

&lt;p&gt;Let me warn you, no bullshits are needed. I am just starting myself and I will be your guide talking mostly about tech. You will be impressed (or not) by how stupid I sound and sometimes how deeply I will talk.&lt;/p&gt;

&lt;p&gt;I hope we could really learn something together and open our horizons. I will maybe throw some jokes out of a context too in an attempt to make things special between us (we never know if I can get you to &lt;em&gt;worship&lt;/em&gt; me later…)&lt;/p&gt;

&lt;p&gt;In that journey, I will throw at you my unique perspective. For instance, being a lazy professional I will always go to the easiest simple route with less work involved. Nothing much fancy, nothing much complex. Just the simple yet sophisticated how to get things done.&lt;/p&gt;

&lt;p&gt;Considering that I am not a native speaker, sometimes I will use my own jargon and maybe it will make you confused but as soon as we get to know each other you will get the gist of it.&lt;/p&gt;

&lt;p&gt;In summary (&lt;strong&gt;TL;DR&lt;/strong&gt;): Nowadays there are a lot of people generating crap/noise (o/). This is just another pretentious guy that thinks that he could do better and his introduction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are you writing anyway?
&lt;/h2&gt;

&lt;p&gt;How many times did you get to a text or a video or even a podcast where someone spent &lt;strong&gt;3000&lt;/strong&gt; lines speaking and speaking and speaking about something that everyone knows and does not have relevance, so in the end (or even worse in the middle) they brought something that is really really interesting but they go and explain it &lt;strong&gt;poorly&lt;/strong&gt; or &lt;strong&gt;wrongly&lt;/strong&gt; and makes everyone &lt;strong&gt;confused&lt;/strong&gt;? &lt;em&gt;(imagine here a poker face, let’s work it out your imagination a little)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yeah. There are &lt;strong&gt;A LOT&lt;/strong&gt; of people like that. There is A LOT of content like that. The Internet brought knowledge and connection but brought a lot of noise as well. Luckily for us, &lt;strong&gt;I am not that guy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Or even a lot of people that get other’s people tutorials/ideas and make a crap version in order to bring attention to themselves?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Nope&lt;/em&gt;. &lt;em&gt;I am not&lt;/em&gt; that guy either.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I propose to do things differently. I do not know if I am going to &lt;em&gt;succeed&lt;/em&gt;. But I might as well try. If I see something &lt;a href="https://www.google.com/search?q=chapada+diamantina+po%C3%A7o+azul"&gt;marvelous&lt;/a&gt; you will have a backlink to the content and maybe a small commentary like &lt;em&gt;“That is *f***&lt;/em&gt; awesome read it and get smart”* &lt;/p&gt;

&lt;p&gt;If I am talking about something that needs explanation. You will get that from me. Concise, direct to the point, and well-explained topics.&lt;/p&gt;

&lt;p&gt;So what I will bring to the table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;**Direct to the point&lt;/em&gt;&lt;em&gt;:&lt;/em&gt; ‘No bullshit attached. You are going to know exactly what I am going to talk about.
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;**“Deep” (as far as my knowledge goes)&lt;/em&gt;&lt;em&gt;:&lt;/em&gt; No “5 silly things that you probably only need to look to understand”. Here you will have thoughtful discussions of how &lt;a href="https://en.wikipedia.org/wiki/Transport_Layer_Security"&gt;SSL(TLS now)&lt;/a&gt; really works from &lt;a href="https://en.wikipedia.org/wiki/Julius_Caesar"&gt;Caesar&lt;/a&gt; times to RSA/DH. How to do a proper search (not using the LIKE operator) with only a database with FTS capabilities. How to configure API Gateway with S3 to trigger lambdas (using CloudFormation). How to profile and improve React component's performance while using nested maps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;It is about myself and it is about others too&lt;/em&gt;&lt;/strong&gt;: Maybe I will make a friend, maybe I found love or hate. Maybe I will be ignored. Who cares…?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Simple kid stupid communication&lt;/em&gt;&lt;/strong&gt;: &lt;em&gt;Layman’s terms&lt;/em&gt; all the way even in the &lt;em&gt;technical&lt;/em&gt; aspects. Like the old man, &lt;a href="https://en.wikipedia.org/wiki/Richard_Feynman"&gt;&lt;em&gt;Feynman&lt;/em&gt;&lt;/a&gt; said (I have not read it much): “I’m smart enough to know that I’m dumb.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portuguese/English content&lt;/strong&gt;: This is also a medium for learning languages. Some of these tutorials will be also written/translated into Portuguese with slight changes. So viewers could get both languages practice. I believe it will be extremely beneficial for my fellow Brazilians.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although I want to guarantee that I will bring insightful content I can not predict the future. After all, I am not mother &lt;a href="https://pt.wikipedia.org/wiki/M%C3%A3e_Din%C3%A1h"&gt;Diná&lt;/a&gt; :P&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QBNJXH06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:800/format:webp/1%2AVE3tI2G6hWQcNvyt3hYZ2Q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QBNJXH06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:800/format:webp/1%2AVE3tI2G6hWQcNvyt3hYZ2Q.jpeg" alt="Mother Diná getting embarrassed to be put on the spot." width="400" height="250"&gt;&lt;/a&gt;&lt;em&gt;Mother Diná getting embarrassed to be put on the spot.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So let’s hope your stay here makes you wiser and if that is not the case at least you can have some fun at my ludicrous jokes. I promise that in that case, I will give you my best.&lt;/p&gt;

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