<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Elian Van Cutsem</title>
    <description>The latest articles on Forem by Elian Van Cutsem (@eliancodes).</description>
    <link>https://forem.com/eliancodes</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%2F498643%2F116c7a21-f9fd-41f9-9ad9-efea648f51b7.jpg</url>
      <title>Forem: Elian Van Cutsem</title>
      <link>https://forem.com/eliancodes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/eliancodes"/>
    <language>en</language>
    <item>
      <title>Elians Astro Startkit</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Thu, 08 Feb 2024 22:29:32 +0000</pubDate>
      <link>https://forem.com/eliancodes/elians-astro-startkit-2o9</link>
      <guid>https://forem.com/eliancodes/elians-astro-startkit-2o9</guid>
      <description>&lt;h1&gt;
  
  
  Releasing my Astro default setup
&lt;/h1&gt;

&lt;p&gt;Every time I set up a new project for myself (using Astro), I find myself installing the same plugins, setting the same settings, and even copy pasting some parts. So I decided to throw it into &lt;a href="https://github.com/ElianCodes/elians-astro-startkit"&gt;a template repo on GitHub&lt;/a&gt; and eventually open up the repository to the public, which is what I did today. Not really to get contributed to, but rather to show others how I develop my personal projects.&lt;/p&gt;

&lt;p&gt;Link to repo: &lt;a href="https://github.com/ElianCodes/elians-astro-startkit"&gt;elians-astro-startkit&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the project contain
&lt;/h2&gt;

&lt;p&gt;You can read the full list of all the technologies I use in the project and why &lt;a href="https://github.com/ElianCodes/elians-astro-startkit"&gt;in the README of the repo&lt;/a&gt;. But to save you time, here is a TLDR;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://astro.build"&gt;Astro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.solidjs.com/"&gt;SolidJS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://biomejs.dev/"&gt;Biome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://unocss.dev/"&gt;UnoCSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Intentions
&lt;/h2&gt;

&lt;p&gt;I quickly wanted to write down some intentions I have for the repo.&lt;/p&gt;

&lt;p&gt;I will update / change it, depending on me changing my "go to" technologies. For instance, at any time in the future, I might change my TypeScript settings or change the design system. Maybe there is an ideal technology that I really want / need but isn't released yet? (Yes, I'm totally talking about Astro Studio).&lt;/p&gt;

&lt;p&gt;Feel free to use the template!&lt;/p&gt;

</description>
      <category>astro</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I'm joining Astro full time!</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Mon, 07 Aug 2023 17:43:01 +0000</pubDate>
      <link>https://forem.com/eliancodes/im-joining-astro-full-time-103l</link>
      <guid>https://forem.com/eliancodes/im-joining-astro-full-time-103l</guid>
      <description>&lt;p&gt;After spending a couple of years at &lt;a href="https://www.vbridge.eu"&gt;vBridge Cloud&lt;/a&gt;, I'm leaving the company. I've worked at vBridge as a software engineer eversince I graduated.&lt;/p&gt;

&lt;p&gt;I had an amazing time there and learned a lot from each and every colleague. Thanks guys! For everything.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz0Jjg_0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ap8vp0zmkxeic3zt9szk.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz0Jjg_0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ap8vp0zmkxeic3zt9szk.jpeg" alt="Picture of the vBridge team" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, it's time for a new adventure! I'm joining the DX-team at &lt;a href="https://astro.build"&gt;Astro&lt;/a&gt; full-time! I'm so excited to be able to work on Astro full-time and help shape the future of web development!&lt;/p&gt;

&lt;p&gt;After being nominated and selected as a maintainer for the project, this always felt like one of the next steps. You can read &lt;a href="https://www.elian.codes/blog/23-04-12-becoming-an-astro-maintainer/"&gt;the blogpost about becoming a maintainer here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After being invited and flying out to Copenhagen to attend the first ever Astro meetup, where I met so many faces behind Astro, I knew that I wanted to stay involved with the project and help out where I could.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l7Quk2LR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqck1frgh2cn8fmoy229.jpg" alt="Picture of the Astro meetup" width="776" height="1035"&gt;&lt;/th&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---C6QB3PZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gd33y4ocegzibig97h4r.jpg" alt="Picture of the Astro 3 displayed on a screen" width="776" height="1035"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Team DX - Astro
&lt;/h2&gt;

&lt;p&gt;The DX-team at Astro is something I've always resonated with. They are responsible for communication, welcoming new people and help them get started with Astro, keeping documentation updated and so much more!&lt;/p&gt;

&lt;p&gt;One of my major tasks, will be the community! (In other words, you guys!)&lt;/p&gt;

&lt;p&gt;Ranging from the weekly community calls, helping the support squad and reviewing and helping you guys make PRs!&lt;/p&gt;

&lt;p&gt;(If you're interested in joining the Astro community, &lt;a href="https://astro.build/chat"&gt;join us on Discord&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Astro has given me so much, ranging from opportunities to travel the world, making new friends and learning so much about open source!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2FJCY6Ub--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/90w79469q6lkxbv6kts3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2FJCY6Ub--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/90w79469q6lkxbv6kts3.jpg" alt="A picture of Elian presenting Astro at JSWorld" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's change the future of web applications!&lt;/p&gt;

&lt;p&gt;Interested to see what I'm doing? Follow me here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/eliancodes"&gt;@ElianCodes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Twitter: &lt;a href="https://twitter.com/eliancodes"&gt;@eliancodes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Mastodon: &lt;a href="https://webtoo.ls/@eliancodes"&gt;@eliancodes&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>astro</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Becoming an Astro maintainer</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Thu, 13 Apr 2023 08:46:00 +0000</pubDate>
      <link>https://forem.com/eliancodes/becoming-an-astro-maintainer-4mbh</link>
      <guid>https://forem.com/eliancodes/becoming-an-astro-maintainer-4mbh</guid>
      <description>&lt;p&gt;A week ago, I got a DM from Dan (&lt;a href="https://github.com/jutanium" rel="noopener noreferrer"&gt;@jutanium&lt;/a&gt;). The DM simply said: "&lt;em&gt;hey, I heard some news came out, any idea what it is?&lt;/em&gt;". I was at a family gathering, so I missed the DM by a couple of hours.&lt;/p&gt;

&lt;p&gt;Turned out, I completely missed a DM from &lt;a href="https://twitter.com/fredkschott" rel="noopener noreferrer"&gt;Fred&lt;/a&gt; (co-founder of Astro and CEO of HTML), saying that I was nominated and voted as a new maintainer on Astro and asking if I would accept. Of course I couldn't be happier 🥳!&lt;/p&gt;

&lt;p&gt;Astro's maintainer and core programs are based on a nomination and voting system, there is no application process. So I wasn't expecting this, but I made a little jump when I read the message!&lt;/p&gt;

&lt;p&gt;It's a real honour and I'm so privileged to be able to work next to so many outstanding people and learn from them!&lt;/p&gt;

&lt;p&gt;👇 Image &lt;a href="https://twitter.com/astrodotbuild/status/1642981721019940866" rel="noopener noreferrer"&gt;Astro tweeted&lt;/a&gt; a couple hours after I accepted!&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%2Fi.imgur.com%2Fbb7O3Nq.jpg" 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%2Fi.imgur.com%2Fbb7O3Nq.jpg" alt="Promo image containing Astro's mascotte with the words "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started in open source
&lt;/h2&gt;

&lt;p&gt;Since I get a lot of questions on how to get started into open source. It's a good time to shine a some light on that topic.&lt;/p&gt;

&lt;p&gt;This is different for everyone, so don't take it as a recipe for success. There was also a lot of luck involved.&lt;/p&gt;

&lt;p&gt;My open source story started somewhere around 2021. I was still studying and working on an essay about frameworks (specifically JAMStack focused) for school and came across Astro. When I read through the documentation for the first time, the concept instantly made something click. It reminded me a lot of PHP, which I used to do a lot. The island architecture looked so simple and useful that I wanted to give it a spin. My first experience with using Astro felt so natural. The onboarding and DX was so awesome!&lt;/p&gt;

&lt;p&gt;Don't take the following as a guide, but if it worked for me, it can work for you too!&lt;/p&gt;

&lt;h3&gt;
  
  
  Astro's Discord
&lt;/h3&gt;

&lt;p&gt;After playing around with Astro for a couple of weeks, I joined &lt;a href="https://astro.build/chat" rel="noopener noreferrer"&gt;their Discord server&lt;/a&gt;. I remember looking at &lt;a href="https://astro.build" rel="noopener noreferrer"&gt;Astro's website&lt;/a&gt; sourcecode and seeing a Discord link show up in the browser's console. I simply had to take a look what was going on there.&lt;/p&gt;

&lt;p&gt;I felt so welcome in the server! Everyone was so friendly and helping each other out. There were a lot of interesting conversations going on about a lot of different topics, which enabled me to learn a lot.&lt;/p&gt;

&lt;p&gt;At that time, the Astro Discord was a small community and because of that, it was easy to talk to core members and ask them questions, which I totally did all the time while I was rebuilding my personal website.&lt;/p&gt;

&lt;h2&gt;
  
  
  My first PR at Astro
&lt;/h2&gt;

&lt;p&gt;While learning Astro, I noticed that the Astro website didn't have a 404 page. I instantly thought; "Hey, I know how to do that!". So I asked in Discord if it was okay to build one and open up a PR. &lt;/p&gt;

&lt;p&gt;I opened my first PR on 6 October 2021: &lt;a href="https://github.com/withastro/astro/pull/1501" rel="noopener noreferrer"&gt;link to PR&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Back then, I was completely new to open source and had totally no idea what I was doing, so yeah, look at me now! I know my mom is proud of me!&lt;/p&gt;

&lt;h2&gt;
  
  
  First talk about Astro
&lt;/h2&gt;

&lt;p&gt;Because I talked a lot to maintainers and core at that time &amp;amp; felt like this was such a new and fresh direction at web development, I decided to try and give a talk about it at a meetup in my city about it. From there, the ball started rolling!&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%2Fi.imgur.com%2FKFZx2CD.jpg" 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%2Fi.imgur.com%2FKFZx2CD.jpg" alt="A picture of Elian speaking in front of an audience at a meetup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;☝️ My first time talking about Astro&lt;/p&gt;

&lt;p&gt;Since then, I've given about a dozen talks about Astro. Most of them were very beginner friendly and -oriented. I hope that I introduced some people to their first steps in the magical universe of Astro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Becoming an Astronaut
&lt;/h2&gt;

&lt;p&gt;After my first talk and some little PRs, I felt like a part of the Astro team! A big boost in that, was &lt;a href="https://twitter.com/afuzzybear2" rel="noopener noreferrer"&gt;Fuzzy&lt;/a&gt; helping me prepare talks, guide me through PR's and awarding me with the unofficial official "Astro Ambassador" title.&lt;/p&gt;

&lt;p&gt;It still baffles me how friendly the whole open source community is. I made a lot of friends among the contributors and core members of Astro and open source in general.&lt;/p&gt;

&lt;p&gt;Another shifting point for me was &lt;a href="https://www.react.brussels/" rel="noopener noreferrer"&gt;React Brussels&lt;/a&gt;. This was my first ever experience at a JS-focused conference. I met so many people that I still talk to, such as &lt;a href="https://twitter.com/jutanium" rel="noopener noreferrer"&gt;Dan&lt;/a&gt; and &lt;a href="https://twitter.com/JoshuaKGoldberg" rel="noopener noreferrer"&gt;Josh&lt;/a&gt;. It motivated me so much to spend more time in open source and Astro in specific.&lt;/p&gt;

&lt;p&gt;You can also check &lt;a href="https://youtu.be/ZIyEZtARlq8" rel="noopener noreferrer"&gt;this interview with Taz from Guild recorded at React Brussels&lt;/a&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%2Fi.imgur.com%2F22LHxKV.jpg" 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%2Fi.imgur.com%2F22LHxKV.jpg" alt="A picture of a room full of people busy talking at React Brussels"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;☝️ Me, talking to people at React Brussels. (Yup, this is where I met Dan and Josh for the first time)&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;There is a lot I want to accomplish as a maintainer at Astro.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The ambassador program at Astro
&lt;/h3&gt;

&lt;p&gt;I want to introduce some kind of ambassador program into Astro! A program where we (as maintainers or core members) help people speaking about Astro, get involved into the community. &lt;strong&gt;Not every contribution to open source, has to be code.&lt;/strong&gt;. This can contain a couple of things, technical writing, blogposts, doing support, giving talks, ... . With this program, I think we could improve the knowledge about Astro.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Astro: Explain It Like I'm Five (ELI5)
&lt;/h3&gt;

&lt;p&gt;A new series where I (or someone else) explains Astro (or maybe even general web) concepts on a very easy-to-understand level! This to increase the general knowledge about Astro and make it accessible to all levels of engineers.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Improve docs
&lt;/h3&gt;

&lt;p&gt;Since I tend to do talks about Astro from time to time, I also see myself as an entrypoint into the Astro ecosystem. Because of that, I get a lot of questions from newcomers to the Astro ecosystem. I try to use those to improve Astro's documentation and examples to make it as easy and accessible for everyone from every skill level as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Get the best DX possible!
&lt;/h3&gt;

&lt;p&gt;One of the reasons I was drawn to Astro was the developer experience. I'm always betting on it and I think Astro still could improve on it. So I'm going to make it one of my goals to keep increasing and learning about developer experience!&lt;/p&gt;

&lt;h2&gt;
  
  
  The future is bright
&lt;/h2&gt;

&lt;p&gt;I'm so happy and excited to be part of Astro's community. I hope to make a positive impact not only in the Astro eco-system, but also in the wider open-source space.&lt;/p&gt;

&lt;p&gt;Don't hesitate to reach out to me! I'm easiest to reach on Discord or &lt;a href="https://twitter.com/eliancodes" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>astro</category>
      <category>opensource</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building Blog tag index pages in Astro</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Wed, 29 Mar 2023 18:03:56 +0000</pubDate>
      <link>https://forem.com/eliancodes/building-blog-tag-index-pages-in-astro-9kb</link>
      <guid>https://forem.com/eliancodes/building-blog-tag-index-pages-in-astro-9kb</guid>
      <description>&lt;p&gt;When I was rebuilding my website with the 2023 redesign. I wanted to add blog tag collection pages as well. This way, people could 'filter' on tags I used in my blog posts. I wanted to do this in a way that was easy to maintain and didn't require me to write a lot of code. So I got hacking on it and found a very neat solution to do this. Here's a little guide on how I implemented it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal
&lt;/h2&gt;

&lt;p&gt;The idea is to generate dynamic pages based on the tags put on the frontmatter of my blogposts. So that the user can search or filter on a tag and get a list of all related blogposts to that tag.&lt;/p&gt;

&lt;p&gt;The blogpost frontmatter validation:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defineCollection&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;astro:content&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;blogCollection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineCollection&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;pubDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="na"&gt;imgUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;default&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="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;As you can see in the codeblock above, the tags are an array of strings. Which means one blogpost can contain multiple tags and one tag can have multiple blogposts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the dynamic page
&lt;/h2&gt;

&lt;p&gt;Of course, tags are dynamic, so the first thing is to build a page with the &lt;code&gt;getStaticPaths()&lt;/code&gt; method in Astro. In my case, that dynamic page is &lt;code&gt;/blog/tags/:tag&lt;/code&gt;. The &lt;code&gt;getStaticPaths()&lt;/code&gt; in Astro should always return a an object that looks like this:&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, that means that the &lt;code&gt;params&lt;/code&gt; object should return the tag string itself and the prop should return an array with all blogposts related to that tag.&lt;/p&gt;

&lt;p&gt;Let's start with getting all tags and build the static pages:&lt;br&gt;
&lt;/p&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 allPosts = await getCollection('blog');

  const tags: string[] = [];

  // using .toLowerCase() here to get rid of case sensitivity
  allPosts.forEach((post) =&amp;gt; {
    post.data.tags.forEach((tag) =&amp;gt; {
      tags.push(tag.toLowerCase());
    });
  });

  // using a new array from a set, we can get rid of duplicate tags 
  return Array.from(new Set(tags)).map((tag) =&amp;gt; {
    return {
      params: { tag },
      // only keep the blogposts that contain the tag itself
      props: {
        blogposts: allPosts.filter((post) =&amp;gt; post.data.tags.map(tag =&amp;gt; tag.toLowerCase()).includes(tag)),
      }
    };
  });
}
---
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when we build the project, all of the tags get specific pages generated for them. with one prop called &lt;code&gt;blogposts&lt;/code&gt;. I'm using the Astro v2.0 Content Collection API, but you can use &lt;code&gt;Astro.glob()&lt;/code&gt; as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the page layout and markup
&lt;/h2&gt;

&lt;p&gt;Now that are pages get generated, we want to display something when the user enters that page. We can define what the dynamic page should look like below the frontmatter.&lt;/p&gt;

&lt;p&gt;Also don't forget to add your &lt;code&gt;Astro.props&lt;/code&gt; object for the page itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import { getCollection } from 'astro:content';
import type { CollectionEntry } from 'astro:content';

import Layout from '../../../layouts/YourLayout.astro';

export async function getStaticPaths() {
  const allPosts = await getCollection('blog');

  const tags: string[] = [];

  allPosts.forEach((post) =&amp;gt; {
    post.data.tags.forEach((tag) =&amp;gt; {
      tags.push(tag.toLowerCase());
    });
  });

  return Array.from(new Set(tags)).map((tag) =&amp;gt; {
    return {
      params: { tag },
      props: {
        blogposts: allPosts.filter((post) =&amp;gt; post.data.tags.map(tag =&amp;gt; tag.toLowerCase()).includes(tag)),
      },
    };
  });
}

interface Props {
  tag: string;
  blogposts: CollectionEntry&amp;lt;'blog'&amp;gt;[];
}

const { blogposts } = Astro.props;
---
&amp;lt;Layout&amp;gt;
  &amp;lt;main&amp;gt;
    &amp;lt;ul&amp;gt;
      { blogposts.map(post =&amp;gt; (
        &amp;lt;li&amp;gt;
          &amp;lt;a href={`/blog/${post.slug}`}&amp;gt;{post.data.title}&amp;lt;/a&amp;gt;
        &amp;lt;/li&amp;gt;
      ))}
    &amp;lt;/ul&amp;gt;
  &amp;lt;/main&amp;gt;
&amp;lt;/Layout&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should now display your layout with a list of all blogposts related to the tag!&lt;/p&gt;

&lt;p&gt;Keep in mind you should still customize this page to fit your needs, otherwise it's kinda ugly.&lt;/p&gt;

&lt;p&gt;If you're interested on how I implemented this on &lt;a href="https://www.elian.codes"&gt;my own website&lt;/a&gt;, you can always take a peek into &lt;a href="https://github.com/eliancodes/eliancodes-frontend"&gt;the source code&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>astro</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Using Tailwind CLI with Blazor</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Thu, 16 Dec 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/eliancodes/using-tailwind-cli-with-blazor-e5l</link>
      <guid>https://forem.com/eliancodes/using-tailwind-cli-with-blazor-e5l</guid>
      <description>&lt;p&gt;Last year &lt;a href="https://www.elian.codes/blog/configure-tailwindcss-with-blazor/" rel="noopener noreferrer"&gt;I wrote an article&lt;/a&gt; about using &lt;a href="https://www.tailwindcss.com" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt; with &lt;a href="https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor" rel="noopener noreferrer"&gt;Blazor&lt;/a&gt;. It was a struggle, since Blazor had to be tricked to install and compile TailwindCSS via PostCSS using &lt;a href="https://www.nodejs.org" rel="noopener noreferrer"&gt;NodeJS&lt;/a&gt;. Yesterday, TailwindCSS launched a new tool called &lt;a href="https://tailwindcss.com/blog/standalone-cli" rel="noopener noreferrer"&gt;Tailwind CLI&lt;/a&gt;. So it's time to revisit trying a combination of TailwindCSS with Blazor!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrapping a new Blazor project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installing dotnet
&lt;/h3&gt;

&lt;p&gt;First of all, you should install a &lt;code&gt;dotnet&lt;/code&gt; version on your local system. Since I use windows, I use &lt;code&gt;choco&lt;/code&gt; to install my dotnet SDK.&lt;br&gt;&lt;br&gt;
You can also install it from &lt;a href="https://dotnet.microsoft.com/en-us/learn/aspnet/blazor-tutorial/install" rel="noopener noreferrer"&gt;their website&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;choco &lt;span class="nb"&gt;install &lt;/span&gt;dotnetcore-sdk &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: I used version dotnet-core 5 for this 'project'&lt;/p&gt;

&lt;h3&gt;
  
  
  Making the project
&lt;/h3&gt;

&lt;p&gt;Starting a new project is easy, just put the follow command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new blazorserver &lt;span class="nt"&gt;-o&lt;/span&gt; YourAppName
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now when you enter the &lt;code&gt;YourAppName&lt;/code&gt; directory, you should be able to start the project in dev mode with &lt;code&gt;dotnet watch run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You should be sent to &lt;code&gt;localhost:5001&lt;/code&gt; which is the default for dotnet apps. Here you'll see an example welcome page built with bootstrap.&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%2Fi.imgur.com%2F2WmOIaq.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%2Fi.imgur.com%2F2WmOIaq.png" alt="Example welcome page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Switching from Bootstrap to Tailwind
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Get rid of Bootstrap
&lt;/h3&gt;

&lt;p&gt;While Bootstrap still is a widely used and good CSS framework, we'll be using TailwindCSS (duh!), so let's delete all files in the &lt;code&gt;css&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Also delete the &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; elements refering to them in &lt;code&gt;Pages/_host.cshtml&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind all the way
&lt;/h3&gt;

&lt;p&gt;Now let's try out Tailwind. First of all we need an executable. The executables can be found on &lt;a href="https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.0.6" rel="noopener noreferrer"&gt;their GitHub repo here&lt;/a&gt;. Be sure to grab the exact one for your OS.&lt;/p&gt;

&lt;p&gt;Once the file is downloaded, move it to the current project directory.&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%2Fi.imgur.com%2FR08wfEI.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%2Fi.imgur.com%2FR08wfEI.png" alt="tailwind executable in project directory"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can make a new config file by running the following command in the project root&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We can now see that a file called &lt;code&gt;tailwind.config.js&lt;/code&gt; is made in the project root! Yay!&lt;/p&gt;

&lt;p&gt;Now let's make a &lt;code&gt;tailwind.css&lt;/code&gt; file in the &lt;code&gt;wwwroot/css&lt;/code&gt; directory with the standard Tailwind imports&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Let's compile tailwind into usable CSS
&lt;/h3&gt;

&lt;p&gt;The only thing we need to do now, is build our Tailwind config into browser ready CSS and link it from our HTML.&lt;/p&gt;

&lt;p&gt;The TailwindCLI has a command for building and watching the css file. At the moment, we still need to give the entire path to the input and output path, but you can build a seperate script to take care of this ofcourse!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./tailwindcss &lt;span class="nt"&gt;-i&lt;/span&gt; ./wwwroot/css/tailwind.css &lt;span class="nt"&gt;-o&lt;/span&gt; ./wwwroot/css/output.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're working on the CSS, you can add the &lt;code&gt;--watch&lt;/code&gt; flag to the command above, the CSS wil then recompile on edits.&lt;/p&gt;

&lt;p&gt;Note: add your &lt;code&gt;output.css&lt;/code&gt; file to the &lt;code&gt;.gitignore&lt;/code&gt; if you're using git, so the file won't get uploaded.&lt;/p&gt;

&lt;p&gt;Now let's add the file to &lt;code&gt;Pages/_host.cshtml&lt;/code&gt; by adding&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"css/output.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now use TailwindCSS as usual!&lt;/p&gt;

</description>
      <category>blazor</category>
      <category>tailwindcss</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I automated SEO to fit my needs</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Fri, 10 Dec 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/eliancodes/how-i-automated-seo-to-fit-my-needs-5b0n</link>
      <guid>https://forem.com/eliancodes/how-i-automated-seo-to-fit-my-needs-5b0n</guid>
      <description>&lt;p&gt;It's been some time since I started writing posts and articles about programming and related. Since the start, I always invested time in SEO, I integrated a system that now works for me. This is an explanation how I did that.&lt;/p&gt;

&lt;p&gt;The following is more of a theoretical explanation rather than real code samples. It will include them, but they can differ depending on frameworks or languages you are using in your projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meta tags
&lt;/h2&gt;

&lt;p&gt;Meta tags are the start of everything for a crawler. That's why I implemented a "frontmatter" to the markdown pages I use to write my blogposts. The frontmatter contains a couple of things:&lt;br&gt;
&lt;/p&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;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🔍 How I automated SEO to work for me&lt;/span&gt;
&lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;12/11/2021 18:27&lt;/span&gt;
&lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Elian&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Van&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Cutsem"&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SEO&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Astro&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Webdevelopment&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;How I automated SEO to work for me&lt;/span&gt;
&lt;span class="na"&gt;imgUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://marketingupdate.nl/wp-content/uploads/2020/05/SEO-Pillar-Post-Art-.png&lt;/span&gt;
&lt;span class="na"&gt;longDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;It's been some time since I started writing posts and articles about programming and related. Since the start, I always invested time in SEO, I integrated a system that now works for me. This is an explanation how I did that.&lt;/span&gt;
&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;../../layouts/BlogPost.astro'&lt;/span&gt;
&lt;span class="na"&gt;permalink&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;12-06-21-how-i-automated-seo-to-work-for-me'&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Yes, this is the exact frontmatter of this very page!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;here follows a guide on what the exact properties in the frontmatter are used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;title: is used as the &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; element in the HTML output and RSS feed&lt;/li&gt;
&lt;li&gt;createdAt: used to fix the order on the blog overview and order in the RSS feed&lt;/li&gt;
&lt;li&gt;author: used in the RSS feed, but also handy if I wanted to quote or invite other writers to use my blog&lt;/li&gt;
&lt;li&gt;tags: a list of relevant tags, put in the meta of the HTML output and added to the RSS feed&lt;/li&gt;
&lt;li&gt;description: same as the &lt;code&gt;title&lt;/code&gt; property, but without the emoji&lt;/li&gt;
&lt;li&gt;imgUrl: used as a social image when my article is shared or previewed in an RSS reader&lt;/li&gt;
&lt;li&gt;longDescription: a relevant short description of the article, mostly the first paragraph&lt;/li&gt;
&lt;li&gt;layout: defines the (astro) layout the blogpost should use, so I can change it when needed&lt;/li&gt;
&lt;li&gt;permalink: used to fix and create a useful (sometimes shorter) link to the article&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When these are converted to HTML at build-time, the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; element will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Primary Meta Tags --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;🔍 How I automated SEO to work for me&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"🔍 How I automated SEO to work for me"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"It's been some time since I started writing posts and articles about programming and related. Since the start, I always invested time in SEO, I integrated a system that now works for me. This is an explanation how I did that."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Open Graph / Facebook --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"website"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://www.elian.codes/blog/12-06-21-how-i-automated-seo-to-work-for-me"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"🔍 How I automated SEO to work for me"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"It's been some time since I started writing posts and articles about programming and related. Since the start, I always invested time in SEO, I integrated a system that now works for me. This is an explanation how I did that."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Twitter --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"twitter:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://www.elian.codes/blog/12-06-21-how-i-automated-seo-to-work-for-me"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"twitter:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"🔍 How I automated SEO to work for me"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"twitter:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"It's been some time since I started writing posts and articles about programming and related. Since the start, I always invested time in SEO, I integrated a system that now works for me. This is an explanation how I did that."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  RSS
&lt;/h2&gt;

&lt;p&gt;An RSS feed might seem like an outdated technology for some, but let me tell you that it isn't. It still commonly used to track different blog and is way handier than having 20 bookmarks in your browser!&lt;/p&gt;

&lt;p&gt;Using an RSS generator is the most easy way to achieve this, there are several RSS-generators available for almost every framework, so you should be able to realise this without to much of a hassle.&lt;/p&gt;

&lt;p&gt;An RSS generator and feed can be broken down into fetching your posts or pages and transfering the raw content into RSS-readable content by the generator.&lt;/p&gt;

&lt;p&gt;Here an example of an RSS feed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;rss&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"2.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;channel&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;![CDATA[ Elian Van Cutsem ]]&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;![CDATA[ Programming and Frontend related articles ]]&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&amp;gt;&lt;/span&gt;https://www.elian.codes/blog.xml&lt;span class="nt"&gt;&amp;lt;/link&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;language&amp;gt;&lt;/span&gt;en-us&lt;span class="nt"&gt;&amp;lt;/language&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;
        &lt;span class="cp"&gt;&amp;lt;![CDATA[ 💄 Use TailwindCSS with Sveltekit (2021) ]]&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;link&amp;gt;&lt;/span&gt;https://www.elian.codes/blog/12-05-21-use-tailwindcss-with-sveltekit-2021/&lt;span class="nt"&gt;&amp;lt;/link&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;
        &lt;span class="cp"&gt;&amp;lt;![CDATA[ Earlier this week, Sveltekit beta got released, ofcourse I wanted to fiddle with it. ]]&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;pubDate&amp;gt;&lt;/span&gt;Sun, 05 Dec 2021 22:45:00 GMT&lt;span class="nt"&gt;&amp;lt;/pubDate&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;
        &lt;span class="cp"&gt;&amp;lt;![CDATA[ 🔧 Set your NodeJS version in Netlify ]]&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;link&amp;gt;&lt;/span&gt;https://www.elian.codes/blog/12-03-21-set-your-node-version-in-netlify/&lt;span class="nt"&gt;&amp;lt;/link&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;
        &lt;span class="cp"&gt;&amp;lt;![CDATA[ A couple of times I needed to fix the NodeJS version on a Netlify site, I found myself googling it a couple of times, so this little how-to is basically a note-to-self. ]]&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;pubDate&amp;gt;&lt;/span&gt;Fri, 03 Dec 2021 08:25:00 GMT&lt;span class="nt"&gt;&amp;lt;/pubDate&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/channel&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/rss&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RSS is mostly in XML, but can also be JSON or ATOM&lt;/p&gt;

&lt;h2&gt;
  
  
  Images &amp;amp; Icons
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Icons
&lt;/h3&gt;

&lt;p&gt;A recognizable favicon is an important step when building or designing a website. These days, most browsers automatically search for &lt;code&gt;/favicon.ico&lt;/code&gt; to set as a favicon, but different formats are also possible (png's, svg's, ...). To set these, I mostly tend to use the following template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- icon Metadata --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/x-icon"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/favicon.ico"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"57x57"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/apple-icon-57x57.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"60x60"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/apple-icon-60x60.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"72x72"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/apple-icon-72x72.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"76x76"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/apple-icon-76x76.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"114x114"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/apple-icon-114x114.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"120x120"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/apple-icon-120x120.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"144x144"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/apple-icon-144x144.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"152x152"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/apple-icon-152x152.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"180x180"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/apple-icon-180x180.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/png"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"192x192"&lt;/span&gt;  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/android-icon-192x192.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/png"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"32x32"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/favicon-32x32.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/png"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"96x96"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/favicon-96x96.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/png"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"16x16"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icons/favicon-16x16.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"manifest"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/manifest.json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"msapplication-TileColor"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"#ffffff"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"msapplication-TileImage"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"/ms-icon-144x144.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"theme-color"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"#ffffff"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"theme-color"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"#6ee7b7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a lot of helpful icon generators online that will output your given icon in the right formats.&lt;/p&gt;

&lt;h3&gt;
  
  
  Images
&lt;/h3&gt;

&lt;p&gt;Images are nice on the eyes, choosing an image that fits your post and will appear everywhere when your post is shared is hard, but really important! People are always more tempted to click on your links when they appear (cfr: Twitter) as images! To do this, just set some simple &lt;code&gt;meta&lt;/code&gt; tags in your &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; element of the page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Open Graph / Facebook --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://www.elian.codes/blog/12-06-21-how-i-automated-seo-to-work-for-me"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://www.elian.codes/assets/img/social.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Twitter --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"twitter:card"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"summary_large_image"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"twitter:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://www.elian.codes/assets/img/social.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Currently I'm building/writing my own social image generator in Go to adjust the title and color dynamically based on the HTML-page title and such! Once that's finished and published, I'll share a post on how it works!&lt;/p&gt;

&lt;p&gt;This will result in something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HonhBcOA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/OyszxOE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HonhBcOA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/OyszxOE.png" alt="example social image" width="800" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Search Console &amp;amp; sitemap
&lt;/h2&gt;

&lt;p&gt;Ofcourse, analytics and insights into your site performance are very useful. To track those, I mostly use the Google ecosystem of SEO-tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sitemap
&lt;/h3&gt;

&lt;p&gt;One of the easiest things to implement is a sitemap. A sitemap allows Google and other search engines to see what pages your website has. When the sitemap gets updated, Google (or another search engine) will try to index and crawl the new pages (except when disallowed by &lt;code&gt;robots.txt&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;(Oh yeah, your RSS feed can serve extra as a sitemap too (but never should replace one)!)&lt;/p&gt;

&lt;h3&gt;
  
  
  Search Console
&lt;/h3&gt;

&lt;p&gt;Google Search Console is a very handy tool which can gove you a better understanding on how your website performs. Not only does it work very well together with Google Analytics, but also gives more insights into who searched what terms when a page of your website was shown in their search results.&lt;/p&gt;

&lt;p&gt;In Google Search Console, you also have access to a tool called "Links", where they show you what pages on the internet contains links to yours. This is very helpful to track who's interested in your content or refering to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Uu4N-y8K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/xAbiLrC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uu4N-y8K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/xAbiLrC.png" alt="My websites performance last three months" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not that long ago, they also launched a new tool called "Search Console Insights", which is a tool designed for content creators to follow up on new content. In the UI of Insights, you'll see how many traffic you got and where they came from, which is great for a quick follow up on your article during a toilet visit.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;robots.txt&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;robots.txt&lt;/code&gt; file is a simple representation of what pages a search engine or crawler is allowed to index.&lt;/p&gt;

&lt;p&gt;Its a very small and simple representation where you disallow certain directories or pages from a specific or all search engines. It also can include your hostname and sitemap so every crawler knows what to look for en where to find it.&lt;/p&gt;

&lt;p&gt;Here's the &lt;code&gt;robots.txt&lt;/code&gt; of &lt;a href="https://www.elian.codes/"&gt;elian.codes&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;User-agent: *
Disallow: 
Host: https://www.elian.codes/
Sitemap: https://www.elian.codes/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since I first started writing posts on this website, I always invested in SEO and I feel that it does it's job well!&lt;/p&gt;

&lt;p&gt;In the last three months, 92% of my website traffic came from organic search&lt;/p&gt;

</description>
      <category>seo</category>
      <category>astro</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Use TailwindCSS with Sveltekit (2021)</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Sun, 05 Dec 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/eliancodes/use-tailwindcss-with-sveltekit-2021-c1c</link>
      <guid>https://forem.com/eliancodes/use-tailwindcss-with-sveltekit-2021-c1c</guid>
      <description>&lt;p&gt;Since my previous blogpost on using &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt; (JIT) with &lt;a href="https://kit.svelte.dev/"&gt;Sveltekit&lt;/a&gt;, a lot has changed. That's why I've updated the article to a newer (and better) method.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Sveltekit
&lt;/h2&gt;

&lt;p&gt;Setting up a new Sveltekit project is not that hard anymore. Just run the following set of commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init svelte@next tailwind-sveltekit-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can always search &lt;a href="https://kit.svelte.dev/docs"&gt;the official documentation&lt;/a&gt; for more info&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding an adapter
&lt;/h3&gt;

&lt;p&gt;In most cases, I tend to use Sveltekit as a static site generator. To tell Sveltekit to create static pages, add the static-adapter with following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @sveltejs/adapter-static@next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also add the following to the &lt;code&gt;svelte.config.cjs&lt;/code&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sveltejs/adapter-static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;kit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells Sveltekit to put the output in the &lt;code&gt;build&lt;/code&gt; folder and dont use a fallback (so generate a &lt;code&gt;index.html&lt;/code&gt;, &lt;code&gt;404.html&lt;/code&gt;, &lt;code&gt;contact.html&lt;/code&gt;, ...)&lt;/p&gt;

&lt;p&gt;more info on the adapter &lt;a href="https://kit.svelte.dev/docs#adapters-supported-environments-static-sites"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding TailwindCSS
&lt;/h2&gt;

&lt;p&gt;Previously I described some additional steps to install Tailwind, like installing autoprefixer and PostCSS. I also setup some extra NPM scripts.&lt;/p&gt;

&lt;p&gt;Since TailwindCSS is used a lot across the web these days, it got way easier. Just use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx svelte-add@latest tailwindcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install TailwindCSS, PostCSS and other dependencies. It will also add the configuration and a basic &lt;code&gt;app.css&lt;/code&gt; file with Tailwind imported.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Set your NodeJS version in Netlify</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Fri, 03 Dec 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/eliancodes/set-your-nodejs-version-in-netlify-1f4d</link>
      <guid>https://forem.com/eliancodes/set-your-nodejs-version-in-netlify-1f4d</guid>
      <description>&lt;p&gt;A couple of times I needed to fix the &lt;a href="https://nodejs.org"&gt;NodeJS&lt;/a&gt; version on a &lt;a href="https://www.netlify.com"&gt;Netlify&lt;/a&gt; site, I found myself googling it a couple of times, so this little how-to is basically a note-to-self.&lt;/p&gt;

&lt;p&gt;The solution to setting a fixed NodeJS version is actually quite easy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;go to your desired website&lt;/li&gt;
&lt;li&gt;go to Site Settings&lt;/li&gt;
&lt;li&gt;under &lt;em&gt;Build &amp;amp; deploy&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;scroll down to &lt;em&gt;Environment&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;add a new environment variable named &lt;code&gt;NODE_VERSION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;set it to your desired version (major or minor)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ijGbU-2G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/dHA6d8B.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ijGbU-2G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/dHA6d8B.png" alt="setting the Node version environment variable in Netlify" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you set it to &lt;code&gt;16&lt;/code&gt;, it will automatically use the latest &lt;code&gt;16.xx.xx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;More information over on the &lt;a href="https://docs.netlify.com/configure-builds/manage-dependencies/"&gt;Netlify documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>jamstack</category>
      <category>netlify</category>
    </item>
    <item>
      <title>Write less code by using CSS Houdini</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Wed, 13 Oct 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/eliancodes/write-less-code-by-using-css-houdini-19l2</link>
      <guid>https://forem.com/eliancodes/write-less-code-by-using-css-houdini-19l2</guid>
      <description>&lt;p&gt;Some time ago I started looking into CSS Houdini. It was awesome already, you could do a lot of cool things with it, but I didn't really see a use of the available things at the time. Today was the day that I looked back at CSS Houdini and refactored some of my code to use CSS Houdini.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the package
&lt;/h2&gt;

&lt;p&gt;The thing I wanted to create in Houdini is my background gradient. This isn't hard to do in CSS or anything, but 1. it was a good practice to learn CSS Houdini 2. required less code 3. now supports CSS custom properties out of the box.&lt;/p&gt;

&lt;p&gt;Writing a package for Houdini isn't that hard (at least, this was a simple one, I imagine some are way harder).&lt;/p&gt;

&lt;p&gt;You start by defining what your package should do:&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ElianCodesBg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;inputProperties&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--color-for-bg&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;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;inputArguments&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;color&amp;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="nf"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fillStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--color-for-bg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&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;/&lt;/span&gt; &lt;span class="mi"&gt;2&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;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&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="nf"&gt;registerPaint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eliancodes-bg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ElianCodesBg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;here we defined that the Worklet should use one input property called &lt;code&gt;--color-for-bg&lt;/code&gt;, which is a color type. Next we define that it should draw a rectangle with half of the width of the element and the same height.&lt;/p&gt;

&lt;p&gt;At last, the Paint get registered as &lt;code&gt;eliancodes-bg&lt;/code&gt; so you can use that in your CSS like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;background-image&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;paint&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;eliancodes-bg&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/eliancodes-bg"&gt;The package is available on NPM&lt;/a&gt;, although it should be fine to load it over CDN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the package
&lt;/h2&gt;

&lt;p&gt;add this code to your html as a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; or add it in an already linked JS-file.&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="nx"&gt;CSS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paintWorklet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://unpkg.com/eliancodes-bg@0.0.1/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;using that javascript, we could just set a custom color in the CSS file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.bg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--color-for-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lightgreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eliancodes-bg&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;depending on the element you set the &lt;code&gt;class="bg"&lt;/code&gt; on, half of the background will be filled with the &lt;code&gt;--color-for-bg&lt;/code&gt; color.&lt;/p&gt;

&lt;p&gt;Check the codepen here: &lt;a href="https://codepen.io/elianvancutsem/pen/wvqaXQV"&gt;https://codepen.io/elianvancutsem/pen/wvqaXQV&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactoring the old code
&lt;/h2&gt;

&lt;p&gt;Now that the package was published I only needed to rewrite some of my older Astro &amp;amp; TypeScript code to use regular CSS and Houdini instead of a lot of TypeScript code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The index background
&lt;/h3&gt;

&lt;p&gt;If you look at my website, one of the first things people notice, is that the background on the homepage has a 50% white, 50% random color gradient. Prevously, the background was generated by a lot of shitty TypeScript code that looked at the class in the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element and would add &lt;code&gt;style="background: linear-gradient(90deg, #FFF 50%, ${color.code} 50%)"&lt;/code&gt; to the element in the case that the &lt;code&gt;dark&lt;/code&gt; (TailwindCSS darkmode) class wasn't there. This was the code before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setBgColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index-bg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)){&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`background: linear-gradient(90deg, #FFF 50%, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 50%)`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`background: linear-gradient(90deg, #000 50%, #000 50%)`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style&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="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;after upgrading to houdini, it got replaced by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--color-for-bg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--color-for-bg&lt;/code&gt; custom property gets used by the Houdini package and will make the background work without any other code!&lt;/p&gt;

&lt;h4&gt;
  
  
  Adding a polyfill
&lt;/h4&gt;

&lt;p&gt;One of the things you notice when playing around with CSS Houdini, is that it's not supported (yet) in all browsers. The Paint API already shipped in chrome, but is still under review in Firefox for example. Luckilly, the guys at Houdini created a polyfill that will make it work with all browsers and it's very easy to add.&lt;/p&gt;

&lt;p&gt;Just add this line in your body to use the polyfill on not-supported browsers:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://unpkg.com/css-paint-polyfill&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The use-color class
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;use-color&lt;/code&gt; class is the class I custom set to change the textcolor of different elements to the active accent-color. Also this got extremely refactored! Before I would manually find all elements with the &lt;code&gt;use-color&lt;/code&gt; class and add a tailwind &lt;code&gt;text-color-${color.class}&lt;/code&gt; class, so that Tailwind would render it correctly.&lt;/p&gt;

&lt;p&gt;To do this, I wrote some code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNewColor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.use-color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`text-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;class&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;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`text-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;getNewColor()&lt;/code&gt; in above example would return a random color from an array with the tailwind class and color code as values.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary-green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#86EFAC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This got refactored to a very simple method where a CSS custom property would get changed from TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--random-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lightgreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.use-color&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--random-color&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNewColor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--random-color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way a lot of code is replaced by way better lines!&lt;/p&gt;

</description>
      <category>css</category>
      <category>javascript</category>
      <category>houdini</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Use API magic to show your most visited pages</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Mon, 04 Oct 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/eliancodes/use-api-magic-to-show-your-most-visited-pages-2mi</link>
      <guid>https://forem.com/eliancodes/use-api-magic-to-show-your-most-visited-pages-2mi</guid>
      <description>&lt;p&gt;A while ago I had an idea for a feature which would show the most frequent visited pages upon a 404 (page not found) error. After I let it sit for a while, I realized that this might be possible by using the &lt;a href="https://developers.google.com/analytics"&gt;Google Analytics Data API&lt;/a&gt; (which I only discovered in research for this feature).&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, you'll need at least some knowledge about building a backend server (could be in any language or framework, but I used &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; in combination with &lt;a href="https://nestjs.com/"&gt;NestJS&lt;/a&gt;) and some general API knowledge.&lt;/p&gt;

&lt;p&gt;You'll also need to integrate &lt;a href="https://analytics.google.com"&gt;Google Analytics&lt;/a&gt; into your website, but you probably guessed that already. (I also won't show that part here)&lt;/p&gt;

&lt;p&gt;The code that I used to get the feature working, you can find in &lt;a href="https://github.com/ElianVanCutsem/ElianCodes-backend"&gt;this repository&lt;/a&gt;. Feel free to fork or re-use in your own projects!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using @elianvancutsem/mostvisitedpages
&lt;/h2&gt;

&lt;p&gt;To fit my personal needs, I built &lt;a href="https://www.npmjs.com/package/@elianvancutsem/mostvisitedpages"&gt;a package on NPM&lt;/a&gt; to do everything I explain here. This package is ofcourse based on the Google Analytics Data API, but simplifies the API by a lot. If you're looking to customize the Google Analytics Data API a lot, go with that, but if you're like me and just want some simple metrics, take a look at &lt;a href="https://www.npmjs.com/package/@elianvancutsem/mostvisitedpages"&gt;@elianvancutsem/mostvisitedpages on NPM&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to talk with Google Analytics API
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/analytics/devguides/reporting/data/v1"&gt;Google Analytics Data API&lt;/a&gt; has great documentation on how to reference and work with the API, so if this article doesn't fill your needs, be sure to checkout the official documentation and &lt;a href="https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport"&gt;reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're like me and want to figur things out yourself, I mainly built the feature using the &lt;a href="https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries"&gt;Client quickstart guide&lt;/a&gt; and searching on from there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enabling the API
&lt;/h3&gt;

&lt;p&gt;First of all, you'll need to enable the API on google's side. If you're using &lt;a href="https://cloud.google.com"&gt;Google Cloud&lt;/a&gt;, this can be done by going to &lt;a href="https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries"&gt;the quickstart&lt;/a&gt; and clicking on 'enable the Google Analytics API' button. You'll then get a dialog asking you to download a JSON file with the credentials looking like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"service_account"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"project_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"project-xxxxxxxxxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"private_key_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xxxxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"private_key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"client_email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xxxxxxxx-xxxxxxxxx@project-xxxxxxxx.iam.gserviceaccount.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"client_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xxxxxxxxxxxxxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"auth_uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://accounts.google.com/o/oauth2/auth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"token_uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://oauth2.googleapis.com/token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"auth_provider_x509_cert_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.googleapis.com/oauth2/v1/certs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"client_x509_cert_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.googleapis.com/robot/v1/metadata/x509/xxxxxxxxx-xxxxxxxxxx%project-xxxxxxxxx.iam.gserviceaccount.com"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you probably guessed, this file contains all the nessecary info to connect to the API as a service account. When you check the IAM policies in &lt;a href="https://console.cloud.google.com"&gt;Google Cloud Console&lt;/a&gt;, you'll also see this service account registered there.&lt;/p&gt;

&lt;h4&gt;
  
  
  Adding Credentials to GA
&lt;/h4&gt;

&lt;p&gt;Now we need to grant this service account access to your Google Analytics property. You can do this by going to [Google Analytics] and adding the &lt;code&gt;client_email&lt;/code&gt; to the property with &lt;code&gt;reading and analyzing&lt;/code&gt; access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install the library
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add @google-analytics/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Do a testrun
&lt;/h3&gt;

&lt;p&gt;(if you're using the simplified &lt;code&gt;@elianvancutsem/mostvisitedpages&lt;/code&gt; version, there is a full example in the &lt;code&gt;README.md&lt;/code&gt; of the package)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BetaAnalyticsDataClient&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;@google-analytics/data&lt;/span&gt;&lt;span class="dl"&gt;'&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;class&lt;/span&gt; &lt;span class="nc"&gt;testRun&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;propertyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nx"&gt;GA_PROPERTY&lt;/span&gt;
  &lt;span class="nx"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BetaAnalyticsDataClient&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;analytics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BetaAnalyticsDataClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;client_email&lt;/span&gt;&lt;span class="p"&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="nx"&gt;GA_EMAIL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;private_key&lt;/span&gt;&lt;span class="p"&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="nx"&gt;GA_KEY&lt;/span&gt;
    &lt;span class="p"&gt;}})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;runReport&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&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="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnalyticsPage&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&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;report&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;analyticsDataClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;runReport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`properties/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propertyId&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="na"&gt;dateRanges&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;startDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;90daysAgo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;endDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;today&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="na"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fullPageUrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pageTitle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;engagedSessions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&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="na"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnalyticsPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineTypeForPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dimensionValues&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;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;morphTitleForOldHeading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dimensionValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dimensionValues&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;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;views&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metricValues&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;value&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="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&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="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;you could always take a look at &lt;a href="https://github.com/ElianVanCutsem/ElianCodes-backend/blob/main/backend/src/analytics/analytics.service.ts"&gt;this GitHub file&lt;/a&gt; for inspiration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add your correct metrics for your report
&lt;/h3&gt;

&lt;p&gt;You can find a list of &lt;a href="https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#metrics"&gt;all possible metrics here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>analytics</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>What's new in TailwindCSS v3</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Sun, 03 Oct 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/eliancodes/what-s-new-in-tailwindcss-v3-1ko6</link>
      <guid>https://forem.com/eliancodes/what-s-new-in-tailwindcss-v3-1ko6</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.0.0-alpha.1"&gt;TailwindCSSv3.0.0-alpha-1&lt;/a&gt; was released yesterday! It's not a full release of v3 yet, but might already give us an insight on what is to come with TailwindCSS v3.&lt;/p&gt;

&lt;p&gt;I went through the release notes and summed up some things that I found importand below.&lt;/p&gt;

&lt;h2&gt;
  
  
  New
&lt;/h2&gt;

&lt;p&gt;In TailwindCSS v3, JIT will be the default compiler mode. If you want to learn more about the Just-In-Time compiler, &lt;a href="https://www.elian.codes/blog/what-is-tailwindcss-jit-and-how-to-use-it/"&gt;check this blogpost&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All colors are enabled by default. Before you had to import them via the &lt;code&gt;tailwind.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;new utilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aspect-ratio&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scroll-snap&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scroll-behavior&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;text-indent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;column&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;touch-action&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;will-change&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;border-x&lt;/code&gt; &amp;amp; &lt;code&gt;border-y&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;new variants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;file:&lt;/code&gt; -&amp;gt; for the native file upload button styling&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;open:&lt;/code&gt; -&amp;gt; for styling native &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; &amp;amp; &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; elements&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using JIT in CDN mode
&lt;/h3&gt;

&lt;p&gt;Before, when using the TailwindCSS CDN, you had to give up on a lot of configuration functionality. Well, that isn't the case anymore since TailwindCSS v3. But TailwindLabs noted: &lt;strong&gt;TailwindCSS CDN JIT is intended for development only, do not use in production!&lt;/strong&gt;. So there is probably still something in the works there.&lt;/p&gt;

&lt;p&gt;Using the TailwindCSS CDN JIT isn't that hard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- add base TailwindCSS --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn-tailwindcss.vercel.app/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

      &lt;span class="c"&gt;&amp;lt;!-- add Plugins --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn-tailwindcss.vercel.app/?plugins=forms,typography,aspect-ratio,line-clamp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

      &lt;span class="c"&gt;&amp;lt;!-- customize config --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;tailwind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;tomato&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tomato&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- add custom styling --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/tailwindcss"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;bg-pink-500;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Breaking
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PostCSS 7 won't be supported any longer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;purge&lt;/code&gt; option in &lt;code&gt;tailwind.config.js&lt;/code&gt; has changed to &lt;code&gt;content&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;overflow-clip&lt;/code&gt; utility was changed to &lt;code&gt;text-clip&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;If you decide on trying TailwindCSS v3 early, be sure to update the &lt;a class="mentioned-user" href="https://dev.to/tailwindcss"&gt;@tailwindcss&lt;/a&gt; dependencies to like &lt;code&gt;@tailwindcss/typography&lt;/code&gt; and &lt;code&gt;@tailwindcss/forms&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can install or upgrade both &lt;code&gt;tailwindcss&lt;/code&gt; and its dependencies by adding &lt;code&gt;@next&lt;/code&gt; as a release:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; tailwindcss@next
npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @tailwindcss/typography@next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All official releasenotes can be found &lt;a href="https://github.com/tailwindlabs/tailwindcss/releases"&gt;on the TailwindCSS GitHub repo&lt;/a&gt;.&lt;br&gt;
Check out the official &lt;a href="https://tailwindcss.com/docs"&gt;TailwindCSS Documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Using PNPM on Netlify</title>
      <dc:creator>Elian Van Cutsem</dc:creator>
      <pubDate>Mon, 27 Sep 2021 00:00:00 +0000</pubDate>
      <link>https://forem.com/eliancodes/using-pnpm-on-netlify-41hg</link>
      <guid>https://forem.com/eliancodes/using-pnpm-on-netlify-41hg</guid>
      <description>&lt;h1&gt;
  
  
  Using PNPM on Netlify
&lt;/h1&gt;

&lt;p&gt;When I first switched my website over to &lt;a href="https://pnpm.io/"&gt;PNPM&lt;/a&gt; instead of &lt;a href="https://yarnpkg.com/"&gt;Yarn&lt;/a&gt;, I noticed that my &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt; build were failing, although I set the build command to &lt;code&gt;pnpm build&lt;/code&gt;. Here's a solution for everyone having the same issue, since I couldn't find any relevant information out there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switching to PNPM
&lt;/h2&gt;

&lt;p&gt;Switching to PNPM locally is almost instant. it's as easy as removing the older &lt;code&gt;package-lock.json&lt;/code&gt; or &lt;code&gt;yarn.lock&lt;/code&gt; file and then installing PNPM. (you can install it using a number of different ways, &lt;a href="https://pnpm.io/installation"&gt;more information here&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;Invoke-WebRequest &lt;span class="s1"&gt;'https://get.pnpm.io/v6.14.js'&lt;/span&gt; &lt;span class="nt"&gt;-UseBasicParsing&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;.Content | node - add &lt;span class="nt"&gt;--global&lt;/span&gt; pnpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PNPM uses a very familiar syntax, so I won't explain further. You just have to track the &lt;code&gt;package.json&lt;/code&gt; and newly generated &lt;code&gt;pnpm-lock.yaml&lt;/code&gt; file to install dependencies on Netlify&lt;/p&gt;

&lt;h2&gt;
  
  
  Telling Netlify to build using PNPM
&lt;/h2&gt;

&lt;p&gt;Netlify offers a few different ways to interact with the build-environment. The easiest (and the one I use), is using the Netlify UI on their website. I will explain further how to use PNPM via the UI, but if you use a &lt;a href="https://docs.netlify.com/configure-builds/file-based-configuration/"&gt;&lt;code&gt;netlify.toml&lt;/code&gt;&lt;/a&gt; file, the approach should be roughly the same.&lt;/p&gt;

&lt;p&gt;Actually, the approach is easy. Netlify doesn't have PNPM installed on their buildenvironment, but they do have NPM &amp;amp; Yarn installed. So we can mis-use them to install PNPM and go on from there. Just add the following as a buildcommand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm build &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; npm &lt;span class="nb"&gt;install &lt;/span&gt;pnpm &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pnpm build &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script will try to run &lt;code&gt;pnpm build&lt;/code&gt; at first. If it fails, because PNPM is not installed, it will install PNPM using NPM and then proceed to run &lt;code&gt;pnpm build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Clever right.&lt;/p&gt;

</description>
      <category>netlify</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
