<?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: jozsefDevs</title>
    <description>The latest articles on DEV Community by jozsefDevs (@jozsefdevs).</description>
    <link>https://dev.to/jozsefdevs</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%2F602904%2F843e75e0-0895-47e7-87df-cf677d5f6dd5.jpeg</url>
      <title>DEV Community: jozsefDevs</title>
      <link>https://dev.to/jozsefdevs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jozsefdevs"/>
    <language>en</language>
    <item>
      <title>🌶️ Hot tip - Use snapshots in React Testing Library to debug faster ⚙️</title>
      <dc:creator>jozsefDevs</dc:creator>
      <pubDate>Mon, 23 Jan 2023 21:06:53 +0000</pubDate>
      <link>https://dev.to/jozsefdevs/hot-tip-use-snapshots-in-react-testing-library-to-debug-faster-42o7</link>
      <guid>https://dev.to/jozsefdevs/hot-tip-use-snapshots-in-react-testing-library-to-debug-faster-42o7</guid>
      <description>&lt;p&gt;So you have this test that is already spitting out something big and complex to DOM and it's failing to find the expected element. You see the usual error message &lt;code&gt;TestingLibraryElementError: Unable to find an element with the text: ...&lt;/code&gt; and absolutely have no idea where things might have gone wrong. Inline errors are nice, however, you can't see the problem. 🙈&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhgdtwn1r8782gda6u3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhgdtwn1r8782gda6u3a.png" alt="Usual error message for failing test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🍀 To solve this we will leverage snapshot testing! 🍀&lt;/p&gt;

&lt;p&gt;Modify your test to get the &lt;code&gt;container&lt;/code&gt; out of render, then make a snapshot with &lt;code&gt;expect(container).toMatchSnapshot()&lt;/code&gt; 🪄. Notice, this trick can be applied regardless of the complexity of your test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbyqmnxtr7f1m1wx7rho0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbyqmnxtr7f1m1wx7rho0.png" alt="Create a snapshot file to better understand your DOM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Re-run your test you'll see the snapshot file 🎉 (&lt;code&gt;App.test.tsx.snap&lt;/code&gt;), which is now totally under your control. &lt;/p&gt;

&lt;p&gt;You can easily spot the problem and search your way through. It's pretty printed and already formatted as your IDE knows this stuff. Feel free to look around and close/open tags &lt;strong&gt;to see what is the actual DOM content at this point of the test&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffp9ldwaolqfuiofrc8vn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffp9ldwaolqfuiofrc8vn.png" alt="Navigable snapshot of your DOM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay, we've found the problem, we missed some additional characters inside. Now we can fix our test. We can rerun and see it's all green 💚.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthll5kzbyfma5p0a7tjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthll5kzbyfma5p0a7tjg.png" alt="Test fixed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🚨 Also, make sure you remove the &lt;code&gt;*.snap&lt;/code&gt; file and the related &lt;code&gt;toMatchSnapshot&lt;/code&gt; line to avoid having unexpected snapshot tests later.&lt;/p&gt;

&lt;p&gt;💡 This technique is especially useful when your component is rendering a huge markup (maybe a composite component already) and you can't find out why your test is not finding an element.&lt;/p&gt;

&lt;p&gt;💡 Also useful to apply this technique if you just want to know the DOM state at a given step. If you are testing a loader with async data, you'll be able to make a snapshot before and after the async data have been loaded.&lt;/p&gt;

&lt;p&gt;Let me know if you find this useful 😊&lt;/p&gt;

&lt;p&gt;Hungry for more RTL tips 🍽️ ? See my previous post ➡️ &lt;a href="https://dev.to/jozsefdevs/top-3-react-testing-library-mistakes-i-should-have-spotted-earlier-9hd"&gt;Top 3 React Testing Library mistakes I should have spotted earlier 🚀&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy testing!&lt;/p&gt;

</description>
      <category>react</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Top 3 React Testing Library mistakes I should have spotted earlier 🚀</title>
      <dc:creator>jozsefDevs</dc:creator>
      <pubDate>Sat, 17 Dec 2022 20:16:06 +0000</pubDate>
      <link>https://dev.to/jozsefdevs/top-3-react-testing-library-mistakes-i-should-have-spotted-earlier-9hd</link>
      <guid>https://dev.to/jozsefdevs/top-3-react-testing-library-mistakes-i-should-have-spotted-earlier-9hd</guid>
      <description>&lt;p&gt;There are a few mistakes that are incredibly easy to make in React Testing Library and I wish I'd watched out for these earlier. Recently I've fixed hundreds of these in a more extensive code base, so just making a remark here. Watch out for these!&lt;/p&gt;

&lt;h2&gt;
  
  
  1 - Await on synchronous queries
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Incorrect code ❌&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;menu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// check for existence&lt;/span&gt;

&lt;span class="c1"&gt;// ❌ Incorrect code ❌&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;banner&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;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queryByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;banner&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;banner&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeInDocument&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// check for non-existence&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the problem is that we're &lt;strong&gt;awaiting on methods that are synchronous&lt;/strong&gt; by default.&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;// ✅ Correct code&lt;/span&gt;
&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;menu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// check for existence&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Correct code&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;banner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queryByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;banner&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;banner&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeInDocument&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// check for non-existence&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Remember, getBy..., queryBy..., getAllBy..., queryAllBy... methods &lt;strong&gt;are synchronous&lt;/strong&gt;. Meaning they're only useful, if your component already rendered elements you want to find. (Probably not a good idea to use these, if your component is making a network request to get the data and just renders after.)&lt;/p&gt;

&lt;p&gt;💡 Check out this related &lt;a href="https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-await-sync-query.md" rel="noopener noreferrer"&gt;eslint-plugin rule&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2 - Not awaiting on asynchronous queries 🙀
&lt;/h2&gt;

&lt;p&gt;This problem is the inverse of the previous one. 🙈&lt;/p&gt;

&lt;p&gt;So let's say your component is only rendered after fetching some network data. In this case, synchronous methods are not helping, because they won't wait for the data to be rendered. In these cases you'll need to use findBy.../findAllBy...&lt;/p&gt;

&lt;p&gt;However there is a problem with the code below ⬇️&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;// ❌ Incorrect code ❌&lt;/span&gt;
&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;menu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// check for existence&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yep, there is no &lt;code&gt;await&lt;/code&gt; used here. This findBy... call &lt;strong&gt;gives us back a promise&lt;/strong&gt;, because it's &lt;strong&gt;always async&lt;/strong&gt;.&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;// ✅ Correct code&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;menu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// check for existence&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Please always &lt;code&gt;await&lt;/code&gt; findBy..., findAllBy... queries.&lt;/p&gt;

&lt;p&gt;💡 Check out this related &lt;a href="https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-query.md" rel="noopener noreferrer"&gt;eslint-plugin rule&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an extra takeaway task, I leave this here for you to find out why this one will always get us fake results. 🙈&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;// ❌ Incorrect code ❌&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;menu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; psst.. this will always pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3 - Using queryBy.. to check existence
&lt;/h3&gt;

&lt;p&gt;Okay, so we can easily decide when to use sync or async methods, but how about this one?&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;// ❌ Incorrect code ❌&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As per documentation, queryBy.. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;returns the matching node for a query, and return null if no elements match. This is useful for asserting &lt;strong&gt;an element that is not present&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;💡 Please only use queryBy..., queryAllBy... queries when you want to check that an element is NOT present.&lt;/p&gt;

&lt;p&gt;💡 Check out this related &lt;a href="https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-presence-queries.md" rel="noopener noreferrer"&gt;eslint-plugin rule&lt;/a&gt;&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;// ✅ Correct code&lt;/span&gt;
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  +1 - Use React Testing Library eslint plugins
&lt;/h3&gt;

&lt;p&gt;You might have noticed already that I've included the related eslint-plugin rules for all the mentioned problems. I love automating rules because they're ensuring good code quality and consistency within the team.&lt;/p&gt;

&lt;p&gt;🚨🚨 You &lt;strong&gt;must&lt;/strong&gt; install &lt;a href="https://testing-library.com/docs/ecosystem-eslint-plugin-testing-library/" rel="noopener noreferrer"&gt;eslint-plugin-testing-library&lt;/a&gt; and &lt;a href="https://testing-library.com/docs/ecosystem-eslint-plugin-jest-dom" rel="noopener noreferrer"&gt;eslint-plugin-jest-dom&lt;/a&gt; if you're working heavily with RTL in your project.&lt;/p&gt;

&lt;p&gt;If you have already a lot of tests (which you should 🙈) eslint won't go easy on you after installing these plugins. However it worth fixing every recommendation it has 💪&lt;/p&gt;

&lt;p&gt;Happy testing!&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://kentcdodds.com/blog/common-mistakes-with-react-testing-library" rel="noopener noreferrer"&gt;Common mistakes with React Testing Library&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Backup/restore most of your Mac's dev tools easily</title>
      <dc:creator>jozsefDevs</dc:creator>
      <pubDate>Sat, 26 Nov 2022 22:00:23 +0000</pubDate>
      <link>https://dev.to/jozsefdevs/backuprestore-most-of-your-macs-dev-tools-easily-5ae1</link>
      <guid>https://dev.to/jozsefdevs/backuprestore-most-of-your-macs-dev-tools-easily-5ae1</guid>
      <description>&lt;p&gt;I was about to make a joke on Twitter the other day, saying how I move to a new Mac is basically about this command:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;brew install yarn nvm cowsay fortune tree direnv gh git-lfs imagemagick jq qpdf webp&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because most of the tools I often use (besides VS Code) are living in the terminal installed by &lt;a href="https://brew.sh/" rel="noopener noreferrer"&gt;brew&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's when I was discovering that brew actually has a subcommand called &lt;a href="https://docs.brew.sh/Manpage#bundle-subcommand" rel="noopener noreferrer"&gt;bundle&lt;/a&gt;. 🤯🤯🤯&lt;/p&gt;

&lt;p&gt;Basically, it generates a "Brewfile" for you (like your beloved package.json files in node projects), writing out a list of packages (called formulaes here) that you have installed. &lt;/p&gt;

&lt;p&gt;All in all, it's a brilliant way to move all your devtools quickly from one Mac to another. &lt;/p&gt;

&lt;h2&gt;
  
  
  Give it a try!
&lt;/h2&gt;

&lt;p&gt;1️⃣ Generate a Brewfile (acting as your lockfile) with&lt;br&gt;
&lt;code&gt;brew bundle dump&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This file is totally human-readable, so when you &lt;code&gt;cat&lt;/code&gt; it, you should see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tap "homebrew/bundle"
tap "homebrew/cask"
tap "homebrew/cask-fonts"
tap "homebrew/core"
brew "cowsay"
brew "direnv"
brew "fortune"
brew "imagemagick"
brew "jq"
brew "neovim"
brew "nvm"
brew "qpdf"
brew "ripgrep"
brew "tree"
brew "yarn"
cask "firefox"
cask "font-hack-nerd-font"
cask "iterm2"
cask "signal"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2️⃣ Carry this Brewfile to your other machine, and just type&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew bundle install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It will install all the dependencies listed in your Brewfile.&lt;/p&gt;

&lt;p&gt;That's it! 💪&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>3 killer tools to debug your Monorepos</title>
      <dc:creator>jozsefDevs</dc:creator>
      <pubDate>Fri, 15 Jul 2022 14:45:29 +0000</pubDate>
      <link>https://dev.to/jozsefdevs/3-killer-tools-to-debug-your-monorepos-4bph</link>
      <guid>https://dev.to/jozsefdevs/3-killer-tools-to-debug-your-monorepos-4bph</guid>
      <description>&lt;p&gt;Lately, I've been doing a lot of migration from single repositories to Monorepos. Here are three very handy tools to make these setups debugging easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  1 - Yarn why / npm ls
&lt;/h2&gt;

&lt;p&gt;If you're using Yarn, this is really useful for checking why a certain dependency is inside your codebase, how it got there and which packages are depending on it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn why react&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://classic.yarnpkg.com/en/docs/cli/why"&gt;Official docs on Yarn why here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're not a Yarn user, you can also use the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm ls&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run this itself to get to know about dependency errors inside your project (marked with red).&lt;/p&gt;

&lt;p&gt;Or you can also check how many times a package got involved in your project by just giving the package name as a parameter&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm ls react&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Be brave about resolving your dependency hells! 🍀&lt;/p&gt;

&lt;h2&gt;
  
  
  2 - Tame your TypeScript configs
&lt;/h2&gt;

&lt;p&gt;So let's say we have something like this for the structure for your monorepo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├─ apps/
│  ├─ frontend/
│  ├─ backend/
├─ packages/
│  ├─ tsconfig/
│  ├─ config/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It could happen that there is a &lt;code&gt;tsconfig.json&lt;/code&gt; in your &lt;code&gt;apps/frontend&lt;/code&gt; and also &lt;code&gt;apps/backend&lt;/code&gt; folders and they're extending a base config from &lt;code&gt;packages/tsconfig&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Also there could be more complex cases, so if you're curious at the end of the day how your final &lt;code&gt;tsconfig.json&lt;/code&gt; will look like for a specific project you can do:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tsc -p apps/frontend --showConfig&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is going to print out the whole merged typescript config what the project will use.&lt;/p&gt;

&lt;p&gt;Original &lt;a href="https://mariusschulz.com/blog/the-showconfig-compiler-option-in-typescript"&gt;idea from here&lt;/a&gt;, big shout out to Marius. 🎉&lt;/p&gt;

&lt;p&gt;I also advise to record this into your root &lt;code&gt;package.json&lt;/code&gt; as&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"tsconfig:debug:frontend": "tsc -p apps/frontend --showConfig"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;to give your team a nifty debug script that they can rely on. &lt;/p&gt;

&lt;h2&gt;
  
  
  3 - Ace your eslint configs
&lt;/h2&gt;

&lt;p&gt;In my experience eslint configurations can blow up really quickly, especially when you're trying to make sense and merge from two different projects. &lt;/p&gt;

&lt;p&gt;🤔 Not sure which plugins/rules are actually being used when you run eslint?&lt;/p&gt;

&lt;p&gt;Try this for one of your files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx eslint --print-config apps/frontend/what/ever/your/file.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will print out all the rules and plugins being used so you can grasp what's happening under the hood.&lt;/p&gt;

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

&lt;p&gt;That's it for today, I wish you Happy debugging! 🤘&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>javascript</category>
      <category>devops</category>
      <category>frontendops</category>
    </item>
    <item>
      <title>How to debug artifact passing on Gitlab easily</title>
      <dc:creator>jozsefDevs</dc:creator>
      <pubDate>Fri, 29 Apr 2022 12:05:27 +0000</pubDate>
      <link>https://dev.to/jozsefdevs/how-to-debug-artifact-passing-on-gitlab-easily-3hd8</link>
      <guid>https://dev.to/jozsefdevs/how-to-debug-artifact-passing-on-gitlab-easily-3hd8</guid>
      <description>&lt;h2&gt;
  
  
  How to debug artifact passing on Gitlab
&lt;/h2&gt;

&lt;p&gt;Lately, I've been working a lot with GitLab pipeline files and I have now a bit more complicated setup than usual. In my case, the middle step is included from another project as a template. I had a nasty bug that from the first step artifacts were never arriving at the last step. However as per Gitlab's docs that should be working by default.&lt;/p&gt;

&lt;p&gt;A simplified version of my &lt;code&gt;gitlab-ci.yml&lt;/code&gt;. Inspiration from &lt;a href="https://stackoverflow.com/a/56550870"&gt;StackOverflow&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image: ubuntu:18.04

stages:
  - test
  - build
  - deploy

test:
  stage: test
  script:
    - echo "test result..." &amp;gt;&amp;gt; test_result.txt
  artifacts:
    paths:
    - "test_result.txt"
    expire_in: 1 day

# runs in stage build
include:
 - project: 'another-project'
   ref: 'master'
   file:
     - '/templates/build.yml' # this creates build_result.txt

# trying to debug if included step can see the artifact from before
included-build:
  script:
    # This is wrong! Overriding the included template's script section
    - cat test_result.txt

# test_result didn't arrive here at all
deploy:
  stage: deploy
  script:
    - cat test_result.txt
    - cat build_result.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;So I wanted to debug why &lt;code&gt;test_result.txt&lt;/code&gt; from the first step never arrived at the last stage.&lt;/p&gt;

&lt;p&gt;My first thought was I can debug this by adding a &lt;code&gt;script&lt;/code&gt; to every step in between to &lt;code&gt;cat test_result.txt&lt;/code&gt; right? Nope!&lt;/p&gt;

&lt;p&gt;Because the included template also introduces a &lt;code&gt;script&lt;/code&gt; section, if I add a &lt;code&gt;script&lt;/code&gt; section to &lt;code&gt;included-build&lt;/code&gt; the included scripts will be overridden. Thus losing the original behavior.&lt;/p&gt;

&lt;p&gt;🔥 Hot tip, you can always validate this by looking through the (View Merged YAML)[&lt;a href="https://docs.gitlab.com/ee/ci/pipeline_editor/#view-expanded-configuration"&gt;https://docs.gitlab.com/ee/ci/pipeline_editor/#view-expanded-configuration&lt;/a&gt;] tab. This way you make sure you see everything merged from templates and won't be surprised :).&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;I discovered that every job can have a &lt;code&gt;before_script&lt;/code&gt;. In my case, this was not used in any steps, so I could use it with confidence. This way I can be sure I don't break any scripts already included.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# trying to debug if included step can see the artifact from before
included-build:
  when: on_success
  before_script:
    # right! Won't change the original behavior of this job
    - cat test_result.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I could add this &lt;code&gt;before_script&lt;/code&gt; section to &lt;strong&gt;every job in between&lt;/strong&gt; the first and last step, and this way found the bug easily. Hopefully, this small tip helps you as well.&lt;/p&gt;

&lt;p&gt;🔥🔥 Extra hot tip, use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow"&gt;Gitlab Workflow VS Code Extension&lt;/a&gt;, it works with on-prem servers as well (not just official gitlab.com projects)!&lt;/p&gt;

&lt;p&gt;You can...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;follow your latest pipeline without stepping out from your VS Code.&lt;/li&gt;
&lt;li&gt;Have &lt;strong&gt;CI variable auto-completion&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Review and create merge requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It just works like a charm, a must-have when working with GitLab.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>gitlab</category>
      <category>tooling</category>
    </item>
    <item>
      <title>How to pass Certified Kubernetes Application Developer (CKAD) Exam</title>
      <dc:creator>jozsefDevs</dc:creator>
      <pubDate>Fri, 30 Apr 2021 14:28:38 +0000</pubDate>
      <link>https://dev.to/jozsefdevs/how-to-pass-certified-kubernetes-application-developer-ckad-exam-3neb</link>
      <guid>https://dev.to/jozsefdevs/how-to-pass-certified-kubernetes-application-developer-ckad-exam-3neb</guid>
      <description>&lt;p&gt;CKAD is a tough 2-hour long exam focusing only on exercises and challenges to be fixed in a real k8s cluster environment. Only practical questions in a terminal with a short time-frame. Here's some magic how I managed to ace it for the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is it so tough?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You have to carry out 19 exercises in 2-hours (yup, roughly 6 mins per challenge). This means you'll have to be fast and on the point. Also you need to complete 66% to pass. To simply put it: Your k8s knowledge has to come from muscle memory. There is no time to read up on forgotten topics.&lt;/li&gt;
&lt;li&gt;It's a proctored exam meaning you'll be watched through your webcam however you can't see or hear the proctor. You can have access to the proctor through a chatbox. You can only have 2 Chrome tabs open. First is the exam, second is the official docs. This created an interesting tension for me from the beginning. So be prepared to find your inner peace ☮️&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kubernetes is using a LOT of objects and also has a LOT of commands to really get what you want. So how to make your k8s knowledge as if it were muscle memory? That's where I used...&lt;/p&gt;

&lt;h2&gt;
  
  
  Anki, anki, anki
&lt;/h2&gt;

&lt;p&gt;Have you ever used flash cards for learning? No? You should give it a try right now! This is my 🪄 secret magic 🪄 to keep up with all types of tech-related knowledge I'm bumping in. Check &lt;a href="https://apps.ankiweb.net/"&gt;Anki's website&lt;/a&gt; it's completely free. It has a &lt;a href="https://docs.ankiweb.net/#/"&gt;great documentation&lt;/a&gt; and also &lt;a href="https://docs.ankiweb.net/#/getting-started?id=videos"&gt;explaining Videos&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Using this tool for me is like defining your own advertisements. When you're binge- watching TV you get a lot of commercials which are simple, short and well-repeated. That's why you can remember them easily after so many years!&lt;/p&gt;

&lt;p&gt;Now imagine your life is a movie... Also that you can create your own ads, but the content for these are actually helping you to master new things. Also, this is better than "telly" because you can control when these ads are showing up! So when I'm noticing just a 5 or 10-minute period in my day where I have nothing to do (this could be either; waiting for a bus; waiting for someone; waiting for the build 🤔 etc.) I will review one of my decks on my phone. Because Anki also has apps compatible with all kind of devices with cloud sync. This is a really great way to learn and there are no more excuses such as "I don't have enough time" or "Ohh shoot.. I have my notes on my other device". &lt;a href="https://docs.ankiweb.net/#/"&gt;Check out the docs&lt;/a&gt; to find out more.&lt;/p&gt;

&lt;p&gt;Getting back to Kubernetes, you don't even need to create your own Deck (set of cards). Because that step usually takes a lot of time before you can actually start learning (revising cards). There is already a shared deck called &lt;a href="https://ankiweb.net/shared/info/959373608"&gt;CKAD Prep exercies&lt;/a&gt;. Use it, update or extend it as you discover new things!&lt;/p&gt;

&lt;p&gt;Revising these cards will make you remember to the most important commands/switches and concepts which I'm going to note just down below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Imperative commands, docs, self-checks
&lt;/h2&gt;

&lt;p&gt;As I said you don't have a lot of time to think. So it's better to cover everything you can with imperative commands because they're real time-savers. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;kubectl run&lt;/code&gt; as often as you can. Almost all switches &lt;a href="https://www.mankier.com/1/kubectl-run"&gt;provided with it&lt;/a&gt; are pretty useful. Take time to see what are these doing: &lt;code&gt;--annotations&lt;/code&gt;, &lt;code&gt;--env&lt;/code&gt;, &lt;code&gt;--labels&lt;/code&gt;, &lt;code&gt;--requests&lt;/code&gt;, &lt;code&gt;--limits&lt;/code&gt;, &lt;code&gt;--serviceaccount&lt;/code&gt;, &lt;code&gt;--port&lt;/code&gt; and &lt;code&gt;--expose&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#create"&gt;kubectl create&lt;/a&gt; is also a key player in this time-saving game.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Combine the &lt;code&gt;run/create&lt;/code&gt; command with &lt;code&gt;--dry-run=client -o yaml&lt;/code&gt; so you can get a preview what you're about to do. Also, you can pipe this into a yaml file and modify further.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are several objects which you can't create through imperative commands. This is the point where you need to &lt;strong&gt;read carefully&lt;/strong&gt; the official docs. If you familiarize yourself with the articles there, the quicker you find important pieces like this section on &lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/"&gt;Persistent Volumes&lt;/a&gt; or this on &lt;a href="https://kubernetes.io/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/"&gt;multi-container pods&lt;/a&gt;. As a general rule of thumb, objects that can't be created with run/create should be copy-pasted out from the docs. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the sake of the exam don't take too much time in official docs on topics which are not part of the &lt;a href="https://github.com/cncf/curriculum/blob/master/CKAD_Curriculum_V1.20.pdf"&gt;CKAD_Curriculum_V1.20&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Self checking is also important. In the real exam environment you won't see whether you performed one task good or not, you have to check it for yourself. You only see the weight of each task in %. This way you'll be able to see quickly if you have already reached the 66% to pass or not. For example if you created a service containing &lt;code&gt;nginx&lt;/code&gt; pods you want to make sure if you do a &lt;code&gt;wget -O- service:80&lt;/code&gt; it works. So prepare to use heavily &lt;code&gt;describe&lt;/code&gt;/&lt;code&gt;get&lt;/code&gt;/&lt;code&gt;exec&lt;/code&gt; and &lt;code&gt;logs&lt;/code&gt; to check back your results. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Further helpful resources
&lt;/h2&gt;

&lt;p&gt;Just a list of bookmarks I kept in my Chrome which are contributed to my success in a huge way. You can boost your learning with these big time 🔥&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/saaguero/ckad-notes"&gt;https://github.com/saaguero/ckad-notes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/dgkanatsios/CKAD-exercises"&gt;https://github.com/dgkanatsios/CKAD-exercises&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://towardsdatascience.com/pass-ckad-certified-kubernetes-application-developer-with-a-score-of-97-af072a65f1ce"&gt;A really good write-up with a lot of tips here&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I hope you find what's written here useful, and it helps you to get a better understanding on your journey. Go &amp;amp;&amp;amp; Ace that exam!&lt;/p&gt;

&lt;p&gt;I would honour your feedback about this post in the comments section below. ⬇️⬇️⬇️ Feel free to write in case of any questions. You can also ping me on Twitter: &lt;a class="mentioned-user" href="https://dev.to/jozsefdevs"&gt;@jozsefdevs&lt;/a&gt;
. Have a wonderful day!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>Pancake stack with fixed header and footer</title>
      <dc:creator>jozsefDevs</dc:creator>
      <pubDate>Mon, 29 Mar 2021 11:51:21 +0000</pubDate>
      <link>https://dev.to/jozsefdevs/pancake-stack-with-fixed-header-and-footer-pko</link>
      <guid>https://dev.to/jozsefdevs/pancake-stack-with-fixed-header-and-footer-pko</guid>
      <description>&lt;p&gt;Not so long ago on one of my projects my task was to refactor our usual Pancake stack. By this we wanted to achieve better maintainability and also better understanding for newcomers. Here I will demonstrate you the separate stages of the fiddling process and of course the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  The task at hand
&lt;/h2&gt;

&lt;p&gt;We had in our code base a usual pancake stack with header, content, footer. Let's describe a bit better all the requirements for this layout:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Header and footer should be always visible in viewport. &lt;/li&gt;
&lt;li&gt;If we have a lot of content the content area should be scrollable. If we have less content the footer should stay on bottom of the viewport.&lt;/li&gt;
&lt;li&gt;Header/footer should be extensible without coding or modifying existing code too much.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So here I show you how it was looking like before the refactor =&amp;gt; &lt;/p&gt;

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

&lt;p&gt;Okay so this solution is just working fine. Also if you check it out on a real mobile device the requirements are still fulfilled. However there are some key problems with it&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;header and footer height is a fix value (meaning we can't easily extend it)&lt;/li&gt;
&lt;li&gt;main element's padding-top and bottom has to know about the height of header and footer. (so heights are actually duplicated in code)&lt;/li&gt;
&lt;li&gt;In this example I wrote the value with &lt;code&gt;calc&lt;/code&gt;, so &lt;code&gt;calc(50px + 10px)&lt;/code&gt; to just highlight that the &lt;code&gt;10px&lt;/code&gt; on the right is the main element's own padding. In the reality this was added together to 60px. So for someone just coming to this code it's really hard to grasp how this height is combined together.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ So it's was a nice start, we covered most of the requirements, but fail to fulfil point 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can we make this better?
&lt;/h2&gt;

&lt;p&gt;Of course, we can iterate once more on this layout code. So notice this new version is also working properly on real mobile devices and has a few noticeable changes. Here it comes:&lt;/p&gt;

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

&lt;p&gt;I will refer with my points here to the little number emojis I placed in the CSS code example:&lt;/p&gt;

&lt;p&gt;1️⃣ We removed every "dependency" from the main section's CSS. So main currently just sets its own padding, which makes it more maintainable in the future. Also it adheres the &lt;a href="https://en.wikipedia.org/wiki/Single-responsibility_principle"&gt;Single Responsibility Principle&lt;/a&gt; in its own weird frontend way. 🤯&lt;br&gt;
2️⃣ While header/footer height is still fix we are using CSS variables. (Notice that this might be not the best solution for you, if you want &lt;a href="https://caniuse.com/?search=CSS%20variables"&gt;IE11 support&lt;/a&gt; still...) So a baby step into a more dynamic version, where we can easily handle if the header gets bigger. See points below.&lt;br&gt;
3️⃣ We can do this trick because we create a &lt;code&gt;:before&lt;/code&gt; and &lt;code&gt;:after&lt;/code&gt; element. Those are having exactly the same height as the header/footer. So this way the content can't go under the real ones because they have their "siblings" underneath.&lt;br&gt;
4️⃣ Here comes the power with CSS variables. Whenever we're adding a new component to the header we just need to change the &lt;code&gt;--header-height&lt;/code&gt; variables height properly. Try fiddling around and push the &lt;code&gt;Toggle header!&lt;/code&gt; button I've placed there to see how the layout would adjust in case of a new component added. Of course for this we need a little JS code to place &lt;code&gt;.big-header&lt;/code&gt; class on the body.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Grid?
&lt;/h2&gt;

&lt;p&gt;Okay so how I went down this path actually... I tried to refactor the initial version to a working CSS Grid solution! That was my motivation to rewrite this layout code in a large SPA. However there were some unexpected hiccups... I will write about that in a follow up post.&lt;/p&gt;

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

&lt;p&gt;Okay that's it! We just made a more reliable Pancake stack layout and also our code became cleaner and more maintainable.&lt;/p&gt;

&lt;p&gt;I would honour your feedback about this post in the comments section below. ⬇️⬇️⬇️ Feel free to write in case of any questions. You can also ping me on Twitter: &lt;a href="https://twitter.com/jozsefDevs"&gt;@jozsefDevs&lt;/a&gt;. Have a wonderful day!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>frontend</category>
      <category>layout</category>
    </item>
  </channel>
</rss>
