<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sean Kerwin</title>
    <description>The latest articles on DEV Community by Sean Kerwin (@seankerwin).</description>
    <link>https://dev.to/seankerwin</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%2F230749%2F918d85a4-f790-4e68-b64a-cf41a71e2525.JPG</url>
      <title>DEV Community: Sean Kerwin</title>
      <link>https://dev.to/seankerwin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/seankerwin"/>
    <language>en</language>
    <item>
      <title>Next.js and Contentlayer static blog guide</title>
      <dc:creator>Sean Kerwin</dc:creator>
      <pubDate>Fri, 02 Sep 2022 13:52:48 +0000</pubDate>
      <link>https://dev.to/seankerwin/nextjs-and-contentlayer-static-markdown-blog-guide-2n8k</link>
      <guid>https://dev.to/seankerwin/nextjs-and-contentlayer-static-markdown-blog-guide-2n8k</guid>
      <description>&lt;p&gt;In this post, I'm going to build a blog demo app using Next.js and the blog will be powered by &lt;a href="https://www.contentlayer.dev/"&gt;Contentlayer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll be making a statically generated, fast and simple blog with no need for a backend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.contentlayer.dev/"&gt;Contentlayer&lt;/a&gt; will power the blog functionality using markdown files that we can commit to our repo.&lt;/p&gt;

&lt;p&gt;Let's get started.&lt;/p&gt;

&lt;p&gt;First, lets create a new Next.js application, you can follow the official guide &lt;a href="https://nextjs.org/docs"&gt;here&lt;/a&gt;. I will be using &lt;code&gt;yarn&lt;/code&gt; for this, but you can use &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;pnpm&lt;/code&gt; also.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn create next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be presented with some options if you use the above command, like the application name.&lt;/p&gt;

&lt;p&gt;Once that has ran, you should navigate into that folder you just created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Contentlayer
&lt;/h2&gt;

&lt;p&gt;Head over to the &lt;a href="https://www.contentlayer.dev/"&gt;official docs&lt;/a&gt; if you want to read more about Contentlayer.&lt;/p&gt;

&lt;p&gt;Add Contentlayer&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add contentlayer next-contentlayer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that has done, open your code in an IDE and open the &lt;code&gt;next.config.js&lt;/code&gt; file, it should look 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="cm"&gt;/** @type {import('next').NextConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;reactStrictMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;swcMinify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="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="nx"&gt;nextConfig&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change it to add the &lt;code&gt;withContentlayer&lt;/code&gt; import&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withContentlayer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-contentlayer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/** @type {import('next').NextConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;reactStrictMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;swcMinify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="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="nx"&gt;withContentlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that out the way, we need to create a new file at the root of our project called &lt;code&gt;jsconfig.json&lt;/code&gt; or &lt;code&gt;tsconfig.json&lt;/code&gt; if using TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"@/components/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"components/*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"contentlayer/generated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./.contentlayer/generated"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"next-env.d.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"**/*.jsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"**/*.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".contentlayer/generated"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we're going to want to create a contentlayer config file in the root of our project called &lt;code&gt;contentlayer.config.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is what I have in mine&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;defineDocumentType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;makeSource&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;contentlayer/source-files&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;computedFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceFileName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;md$/&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineDocumentType&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="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;Post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;filePathPattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`posts/*.md`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;publishedAt&lt;/span&gt;&lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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;wordCount&lt;/span&gt;&lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/gu&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;computedFields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;makeSource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;contentDirPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;documentTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Post&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;What this is doing is specifying a single document type called &lt;code&gt;Post&lt;/code&gt; and they're all going to live inside a folder called &lt;code&gt;data/posts/*.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can read more about how this works &lt;a href="https://www.contentlayer.dev/docs/getting-started"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We're going to create two new folders, in the root of our project, create a folder called &lt;code&gt;data&lt;/code&gt;, then inside that, create another called &lt;code&gt;posts&lt;/code&gt;. The reason we're nesting it like this, is once you get your head around Contentlayer, you can extend the config above to define different document types, for instance, you might want to have &lt;code&gt;Posts&lt;/code&gt;, &lt;code&gt;Projects&lt;/code&gt; and &lt;code&gt;Guides&lt;/code&gt; all stored inside your code.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;data/posts&lt;/code&gt; folder, create some markdown files that have the following format:&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Lorem&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Ipsum"&lt;/span&gt;
&lt;span class="na"&gt;publishedAt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2022-06-24&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="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Nextjs'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;React'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="s"&gt;// optional&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/static/post-1-hero.webp'&lt;/span&gt; &lt;span class="s"&gt;// optional&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

Mollit nisi cillum exercitation minim officia velit laborum non Lorem
adipisicing dolore. Labore commodo consectetur commodo velit adipisicing irure
dolore dolor reprehenderit aliquip. Reprehenderit cillum mollit eiusmod
excepteur elit ipsum aute pariatur in. Cupidatat ex culpa velit culpa ad non
labore exercitation irure laborum.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The title and publishedAt are required, but the tags and image are not, they're optional, (we specified this in the config above) so try and create some posts with and without the optional fields.&lt;/p&gt;

&lt;p&gt;The folder structure should be the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs/
├─ posts/
│  ├─ post-1.md
│  ├─ post-2.md
│  ├─ post-3.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You are free to call these markdown files whatever you want, keep them lower-case and hyphenated as this will be the slug/url for that post.&lt;/p&gt;

&lt;p&gt;Before we go any further, lets test that contentlayer is all hooked up correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all works, you should get an output a bit like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info  - SWC minify release candidate enabled. https://nextjs.link/swcmin
Generated 3 documents in .contentlayer
event - compiled client and server successfully in 1225 ms (178 modules)
wait  - compiling...
event - compiled client and server successfully in 49 ms (178 modules)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;Generated 3 documents in .contentlayer&lt;/code&gt; bit, that tells us that we've hooked contentlayer up and its generated 3 files based on our markdown files.&lt;/p&gt;

&lt;p&gt;If we look in our project, a &lt;code&gt;.contentlayer&lt;/code&gt; folder has been created, don't edit anything inside of here as it gets regenerated each time things are changed. But if we go take a look, we should have a folder inside called &lt;code&gt;generated&lt;/code&gt; and a &lt;code&gt;Post&lt;/code&gt; folder inside that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
└── .contentlayer/
    ├── .cache
    └── generated/
        └── Post/
            ├── _index.json
            ├── _index.mjs
            ├── posts__post-1.md.json
            ├── posts__post-2.md.json
            └── posts__post-3.md.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take a look at one of the files, &lt;code&gt;posts__post-1.md.json&lt;/code&gt; and it will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "title": "My first blog post",
  "publishedAt": "2022-06-24T00:00:00.000Z",
  "tags": [
    "Nextjs",
    "React"
  ],
  "image": "/static/post-1-hero.webp",
  "body": {
    "raw": "\nMollit nisi cillum exercitation minim officia velit laborum non Lorem\nadipisicing dolore. Labore commodo consectetur commodo velit adipisicing irure\ndolore dolor reprehenderit aliquip. Reprehenderit cillum mollit eiusmod\nexcepteur elit ipsum aute pariatur in. Cupidatat ex culpa velit culpa ad non\nlabore exercitation irure laborum.\n",
    "html": "&amp;lt;p&amp;gt;Mollit nisi cillum exercitation minim officia velit laborum non Lorem\nadipisicing dolore. Labore commodo consectetur commodo velit adipisicing irure\ndolore dolor reprehenderit aliquip. Reprehenderit cillum mollit eiusmod\nexcepteur elit ipsum aute pariatur in. Cupidatat ex culpa velit culpa ad non\nlabore exercitation irure laborum.&amp;lt;/p&amp;gt;"
  },
  "_id": "posts/post-1.md",
  "_raw": {
    "sourceFilePath": "posts/post-1.md",
    "sourceFileName": "post-1.md",
    "sourceFileDir": "posts",
    "contentType": "markdown",
    "flattenedPath": "posts/post-1"
  },
  "type": "Post",
  "slug": "post-1"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this file, we can see what contentlayer has generated, we've got &lt;code&gt;body.html&lt;/code&gt; from our Markdown content, our slug, tags, date and title all there. Now lets use that inside react!&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering the posts
&lt;/h2&gt;

&lt;p&gt;We're going to keep this simple by just using the &lt;code&gt;index.js&lt;/code&gt; page to fetch our content, but we could if we wanted to, break this out into a separate page.&lt;/p&gt;

&lt;p&gt;Open up the &lt;code&gt;pages/index.js&lt;/code&gt; file and delete everything inside of it, we're going to start fresh.&lt;/p&gt;

&lt;p&gt;I'm a big fan of arrow functions but if you want to use a traditional function, that's fine.&lt;/p&gt;

&lt;p&gt;Place this inside the &lt;code&gt;inedx.js&lt;/code&gt; file to get started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Hello world.
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;If you run the app with &lt;code&gt;yarn dev&lt;/code&gt; now, and open it in a browser, &lt;code&gt;http://localhost:3000&lt;/code&gt;, you should see a blank page with &lt;code&gt;hello world&lt;/code&gt; in the corner. If so, great! Let's move on.&lt;/p&gt;

&lt;p&gt;Now update your index.js file to have the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;allPosts&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;contentlayer/generated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publishedAt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publishedAt&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;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;posts&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;posts&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Hello world!
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;What we're doing here is adding the &lt;code&gt;allPosts&lt;/code&gt; import that contentlayer generated, remember the &lt;code&gt;.contentlayer&lt;/code&gt; folder, take a look in there at the &lt;code&gt;_index.mjs&lt;/code&gt; file, that's where the &lt;code&gt;allPosts&lt;/code&gt; function comes from.&lt;/p&gt;

&lt;p&gt;We're going to use Next.js &lt;code&gt;getStaticProps&lt;/code&gt; method (which is asynchronous) - &lt;code&gt;getStaticProps&lt;/code&gt; is a method to tell Next.js to pre-render this page at build time, and use the props provided by &lt;code&gt;getStaticProps&lt;/code&gt;. You can read more about this &lt;a href="https://nextjs.org/docs/basic-features/data-fetching/get-static-props"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We're then passing &lt;code&gt;posts&lt;/code&gt; to the &lt;code&gt;Index&lt;/code&gt; method, and if you &lt;code&gt;console.log(posts)&lt;/code&gt; inside that, you'll be able to see them on the running app console.&lt;/p&gt;

&lt;p&gt;I also created a folder at the root of my project called &lt;code&gt;static&lt;/code&gt; with some images inside &lt;code&gt;post-1-hero.webp&lt;/code&gt; which is what is in the markdown file for the &lt;code&gt;image&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;This is my final &lt;code&gt;index.js&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;allPosts&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;contentlayer/generated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Image&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;next/image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allPosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publishedAt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publishedAt&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;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;posts&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;posts&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;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"posts"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Posts&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publishedAt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Loop through any tags if we have any */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;


            &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;200px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;relative&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"fill"&lt;/span&gt; &lt;span class="na"&gt;objectFit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"cover"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;  
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Post body */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;If you've followed this guide, you should be able to start your project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and see some &lt;code&gt;posts&lt;/code&gt; on the page. &lt;/p&gt;

&lt;p&gt;This will all be statically generated at build time which is great for speed, no need for a back-end to store your blog posts any more, just add a new post markdown file, commit it, and run a build/deploy.&lt;/p&gt;

&lt;p&gt;Whilst there are so many things that can be done with Contentlayer, you can look at adding pagination, fetching next and previous posts and having multiple document types, all within the same code-base.&lt;/p&gt;

&lt;p&gt;I really like contentlayer and the fact that it means I can write blog posts/article and just store them in my Git repo, posts can then be version controlled and I don't have the overhead of running a server to store the posts.&lt;/p&gt;

&lt;p&gt;Feel free to checkout this code in my repo &lt;a href="https://github.com/lordkerwin/nextjs-contentlayer-demo"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also use Contentlayer on my personal website, you can see the code for that &lt;a href="https://github.com/lordkerwin/v2"&gt;here&lt;/a&gt; or see it in action by going to &lt;a href="https://seankerwin.dev"&gt;seankerwin.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>tutorial</category>
      <category>react</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Pop!_OS - The first week!</title>
      <dc:creator>Sean Kerwin</dc:creator>
      <pubDate>Wed, 04 Aug 2021 21:31:01 +0000</pubDate>
      <link>https://dev.to/seankerwin/pop-os-the-first-week-3k0i</link>
      <guid>https://dev.to/seankerwin/pop-os-the-first-week-3k0i</guid>
      <description>&lt;p&gt;Hey everyone.&lt;/p&gt;

&lt;p&gt;So, I'm an avid Apple Mac user, and I've used macOS as my primary dev environment for over 10 years.&lt;/p&gt;

&lt;p&gt;This has been mostly down to that my employer provided me with a top end Macbook Pro, so I have done everything within the apple ecosystem.&lt;/p&gt;

&lt;p&gt;My current employer, the boss was pretty cool, I could set my mac's up how I wanted, have personal emails/icloud on it, use it for personal stuff and side-work (out of work hours ofcourse), So I've had no real reason to switch.&lt;/p&gt;

&lt;p&gt;I have just taken a new job, and decided that I want my own machine, keep work and personal stuff separated.&lt;/p&gt;

&lt;p&gt;Dell were doing an amazing deal on their outlet website for the XPS range of laptops, and I managed to pickup a brand-new XPS 13 9305 with 16GB Ram, and i7 Quad Core, with 512GB M2 SSD, for £800.&lt;/p&gt;

&lt;p&gt;The only problem is that it came with Windows 10 Home edition. I tried to use Windows with WSL2, but felt like it was a fight to get even the basics to work. Windows lasted less than a day on the laptop before I decided to install Linux.&lt;/p&gt;

&lt;p&gt;I've used Mint/Ubuntu before, and I know of System76 (who make awesome Linux machines by the way!) System76 also have developed Pop!_OS, a Ubuntu/Debian based OS that is, well, fucking amazing!&lt;/p&gt;

&lt;p&gt;It's aimed at developers and is built from the ground up with that in mind. The keyboard shortcuts for multi-tasking is outstanding. I love the tile-view that comes and the global launcher/search makes me feel right at home, just like macOS and its Spotlight.&lt;/p&gt;

&lt;p&gt;Now, for installing it on the XPS, it was a simple case of heading over to the Pop!_OS website and grabbing the correct ISO that you need.&lt;/p&gt;

&lt;p&gt;I grabbed the 21.04 Non Nvidia version (as my laptop just has the Intel Iris XE graphics). Create a bootable USB and installed it on the XPS.&lt;/p&gt;

&lt;p&gt;Aside from turning safe-boot off in the BIOS of the XPS, I did nothing else. Followed the on-screen instructions when installing the OS, I wiped my SSD and only have PopOS! as my main operating system.&lt;/p&gt;

&lt;p&gt;Once it was installed, I opened the Pop!_Shop to let it check for updates and install them.&lt;/p&gt;

&lt;p&gt;So far, I've been running PopOS! for over a week, and haven't had a single issue.&lt;/p&gt;

&lt;p&gt;I have the XPS plugged via USB-C to DisplayPort for a Iiyama 34" Ultrawide running at 144hz, and a Seagate Barracuda Gaming Dock via Thunderbolt (Which has a 4TB Spinning drive and a 512GB M2-SSD inside it) and everything is working perfectly.&lt;/p&gt;

&lt;p&gt;I have things like Docker, PHP, Node, Jetbrains (WebStorm, PhpStorm and DataGrip), Visual Studio Code, Mailspring (For emails) and it even plays nicely with my Corsair Virtuso Headset.&lt;/p&gt;

&lt;p&gt;I could seriously see Pop!_OS replacing my Mac as a daily driver. &lt;/p&gt;

&lt;p&gt;I've never had such a great experience with a Linux distro before.&lt;/p&gt;

&lt;p&gt;You can checkout Pop!_OS here.&lt;br&gt;
&lt;a href="https://pop.system76.com/"&gt;https://pop.system76.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
    </item>
    <item>
      <title>Day.js with RelativeTime in Nuxt.js</title>
      <dc:creator>Sean Kerwin</dc:creator>
      <pubDate>Tue, 23 Feb 2021 23:21:42 +0000</pubDate>
      <link>https://dev.to/seankerwin/day-js-with-relativetime-in-nuxt-js-3kk9</link>
      <guid>https://dev.to/seankerwin/day-js-with-relativetime-in-nuxt-js-3kk9</guid>
      <description>&lt;p&gt;This is a relatively short guide, and it's just to show how easy it is to implement &lt;a href="https://day.js.org/"&gt;day.js&lt;/a&gt; inside a Nuxt app.&lt;/p&gt;

&lt;p&gt;I've always just used Moment.js for date formatting, but since Moment.js has now been abandoned and they're encouraging people to use alternatives, I needed to find a way to convert timestamps that are provided by the API's I consume. They usually return timestamps in the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2020-10-08T07:51:58Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which to be honest, isn't really useful to anyone. That's where day.js comes in, it can convert the timestamp above into something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Oct 8th 2020
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's pretty simple to do.&lt;/p&gt;

&lt;p&gt;First we need to pull in the &lt;code&gt;@nuxtjs/dayjs&lt;/code&gt; package with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @nuxtjs/dayjs
or
npm install @nuxtjs/dayjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that is installed, open up your &lt;code&gt;nuxt.config.js&lt;/code&gt; and add&lt;br&gt;
&lt;code&gt;'@nuxtjs/dayjs'&lt;/code&gt; to the &lt;code&gt;modules&lt;/code&gt; section, and then outside of that, add the following &lt;code&gt;dayjs&lt;/code&gt; object.&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;modules&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;@nuxtjs/dayjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="nx"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;locales&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;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;defaultLocale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;plugins&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;relativeTime&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="s1"&gt;advancedFormat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set any &lt;em&gt;locales&lt;/em&gt; you want, for me, being in the United Kingdom, I set my locale to &lt;code&gt;en&lt;/code&gt; and then add any additional dayjs plugins you need. I'm using the &lt;a href="https://day.js.org/docs/en/plugin/relative-time"&gt;RelativeTime&lt;/a&gt; and &lt;a href="https://day.js.org/docs/en/plugin/advanced-format"&gt;AdvancedFormat&lt;/a&gt; plugins.&lt;/p&gt;

&lt;p&gt;Once everything is installed, you from within any component you can do the following&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="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;$dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2020-10-08T07:51:58Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MMM Do YYYY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which will output this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Oct 8th 2020
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use the RelativeTime plugin to turn it into 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="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;$dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2020-10-08T07:51:58Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;fromNow&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;Which will return&lt;/p&gt;

&lt;p&gt;&lt;code&gt;a year ago&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can obviously, not use hard-coded dates and use props/variables such as&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="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;$dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;published_at&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;fromNow&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;Day.js is a simple and ultra-lightweight replacement for Moment.js and is super easy to use.&lt;/p&gt;

</description>
      <category>dayjs</category>
      <category>nuxt</category>
      <category>vue</category>
    </item>
    <item>
      <title>Nuxt.js + Tailwind 2.0</title>
      <dc:creator>Sean Kerwin</dc:creator>
      <pubDate>Sat, 19 Dec 2020 23:31:57 +0000</pubDate>
      <link>https://dev.to/seankerwin/nuxt-js-tailwind-2-0-1979</link>
      <guid>https://dev.to/seankerwin/nuxt-js-tailwind-2-0-1979</guid>
      <description>&lt;p&gt;In the post, i'm going to explain how to use the new Tailwind 2.0 with Nuxt.js.&lt;/p&gt;

&lt;p&gt;By default, when you create a new Nuxt project, it comes with tailwind 1.X. To utilize the new Tailwind 2.0 and it's new classes you'll need to make some changes.&lt;/p&gt;

&lt;p&gt;As of writing this post. There is a PR out for Nuxt and Tailwind 2.0, there's currently an issue because Nuxt 2.14 still uses PostCSS 7. Tailwind 2.0 requires PostCSS 8. You can checkout the PR &lt;a href="https://github.com/nuxt-community/tailwindcss-module/pull/203"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The good people over at Tailwind have made a compatibility build, allowing us to use PostCSS 7 with Tailwind 2. Nuxt 2.15 should be using PostCSS 8 but again, as of writing this, Nuxt 2.14 is using PostCSS 7.&lt;/p&gt;

&lt;p&gt;What I did to get Tailwind 2.0 working on a fresh project is the following:&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;create-nuxt-app tailwind-v2&lt;/code&gt; to create a project.&lt;/p&gt;

&lt;p&gt;I answered the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; Project name: tailwind-v2
&amp;gt; Programming language: JavaScript
&amp;gt; Package manager: Yarn
&amp;gt; UI framework: Tailwind CSS
&amp;gt; Testing framework: None
&amp;gt; Rendering mode: Universal (SSR / SSG)
&amp;gt; Deployment target: Server (Node.js hosting)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new project, but using Tailwind 1.X, I then went on to do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add --dev tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add the compatibility build to your project.&lt;/p&gt;

&lt;p&gt;I then ran &lt;code&gt;npx tailwind init&lt;/code&gt; to generate a tailwind.config.js and added the new &lt;code&gt;tailwind/forms&lt;/code&gt; package required in tailwind 2.0 for the form styling to test it out.&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;tailwind.config.js&lt;/code&gt; just looks like this for the demo project.&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;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;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&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="c1"&gt;// or 'media' or 'class'&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;variants&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tailwindcss/forms&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;And that's basically it.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;yarn dev&lt;/code&gt; in your terminal and then head-over to &lt;a href="https://tailwindui.com"&gt;https://tailwindui.com&lt;/a&gt; to test out the new pre-built Tailwind 2.0 components.&lt;/p&gt;

</description>
      <category>nuxt</category>
      <category>vue</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Angular + Firebase Hosting + Gitlab</title>
      <dc:creator>Sean Kerwin</dc:creator>
      <pubDate>Sat, 17 Oct 2020 10:35:30 +0000</pubDate>
      <link>https://dev.to/seankerwin/angular-firebase-hosting-gitlab-ci-cd-staging-production-530c</link>
      <guid>https://dev.to/seankerwin/angular-firebase-hosting-gitlab-ci-cd-staging-production-530c</guid>
      <description>&lt;p&gt;So in the short guide, I'm going to show you how I deploy an angular site to Google's firebase hosting using Gitlabs CI/CD Pipelines to do all the build and deploy for me.&lt;/p&gt;

&lt;p&gt;I'm also going to be doing a staging / production builds, this way I can see things in staging and test/play and when i'm happy, push my changes to the repo's &lt;code&gt;main/master&lt;/code&gt; branch and Gitlab will deploy it all to production.&lt;/p&gt;

&lt;p&gt;Ok, so first thing, we need the Firebase CLI installed, using the following 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;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; firebase-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that is all done, head over to the &lt;a href="https://console.firebase.google.com/" rel="noopener noreferrer"&gt;Firebase Console&lt;/a&gt; and create 2 new projects: &lt;/p&gt;

&lt;p&gt;For this demo, I created 2 &lt;/p&gt;

&lt;p&gt;&lt;code&gt;fir-hosting-demo-staging&lt;/code&gt;&lt;br&gt;
and&lt;br&gt;
&lt;code&gt;fir-hosting-demo-prod&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You need to have 2 seperate projects if you want to deploy to staging and then production, if you don't, just create the one project.&lt;/p&gt;

&lt;p&gt;Once they're created, head back over to your Angular application, we've got a bit of preparation to do.&lt;/p&gt;

&lt;p&gt;Navigate to your angular application using a terminal and run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;firebase init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Highlight the &lt;code&gt;hosting&lt;/code&gt; option and then the &lt;code&gt;Use an existing project&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;Select your &lt;em&gt;Staging&lt;/em&gt; project from the list that you get by using the arrow keys.&lt;/p&gt;

&lt;p&gt;You'll then be asked the question&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;What &lt;span class="k"&gt;do &lt;/span&gt;you want to use as your public directory?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the path that is set in the &lt;code&gt;angular.json&lt;/code&gt; for &lt;code&gt;outputPath&lt;/code&gt;, it's the path that everything goes to when you run &lt;code&gt;ng build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For me, it is &lt;code&gt;dist/firebase-hosting-demo&lt;/code&gt; as that is the name of my Angular application. So set it to that.&lt;/p&gt;

&lt;p&gt;You'll then be asked about redirects and as its an angular application, you'll want to select &lt;code&gt;yes&lt;/code&gt; to redirect everything to &lt;code&gt;index.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you have ran this command, open up the newly created file called &lt;code&gt;.firebaserc&lt;/code&gt; and it should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "projects": {
    "default": "fir-hosting-demo-staging"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like to rename my project alias, so go ahead and change &lt;code&gt;default&lt;/code&gt; to &lt;code&gt;staging&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "projects": {
    "staging": "fir-hosting-demo-staging"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're now going to add our production hosting, run the following command in the terminal.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;firebase use --add&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You'll then be given a list of your current firebase projects, select the production one you created.&lt;/p&gt;

&lt;p&gt;You then have to give it an alias, I like to call mine &lt;code&gt;production&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you head over to the &lt;code&gt;.firebaserc&lt;/code&gt; file, it should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "projects": {
    "staging": "fir-hosting-demo-staging",
    "production": "fir-hosting-demo-prod"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now in the terminal of that project, just run&lt;/p&gt;

&lt;p&gt;&lt;code&gt;firebase use staging&lt;/code&gt; and it will switch to use the staging project, same for &lt;code&gt;firebase use production&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, if everything has been setup right, you can go ahead and do a test build/deploy.&lt;/p&gt;

&lt;p&gt;In your terminal, make sure you're using &lt;code&gt;staging&lt;/code&gt; by running &lt;br&gt;
&lt;code&gt;firebase use staging&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Build your Angular application using the command&lt;br&gt;
&lt;code&gt;ng build&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once that has built, you should have a &lt;code&gt;dist&lt;/code&gt; folder with your application inside, for me it's &lt;code&gt;dist/firebase-hosting-demo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Go ahead and run the command &lt;code&gt;firebase deploy --only hosting&lt;/code&gt; and watch as Firebase will now take all the built files from the output folder and upload them to firebase staging branch.&lt;/p&gt;

&lt;p&gt;Once that has completed, the firebase cli will return a Hosting URL where you can see you staging application.&lt;/p&gt;

&lt;p&gt;You can do the same for the production branch buy running the command to switch to production &lt;code&gt;firebase use production&lt;/code&gt; and then the same &lt;code&gt;firebase deploy --only hosting&lt;/code&gt; and the same files will be pushed to the production project in firebase.&lt;/p&gt;

&lt;p&gt;This is good for testing, but it will become a bit tedious to remember which branch you're on, which project you're using and remembering that you need to build/push your code.&lt;/p&gt;

&lt;p&gt;This is where we're going to leverage Gitlab and let it do all of the work for you.&lt;/p&gt;

&lt;p&gt;Other CI/CD tools can do the same, I just mainly use Gitlab.&lt;/p&gt;

&lt;p&gt;So now this is all setup, let's move onto the next step!&lt;/p&gt;
&lt;h1&gt;
  
  
  Gitlab
&lt;/h1&gt;

&lt;p&gt;If you have your code all stored in Gitlab, the way I like to work is have 3 branches, &lt;code&gt;master&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt;, and &lt;code&gt;develop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;master&lt;/code&gt; and &lt;code&gt;staging&lt;/code&gt; are protected branches and cannot be pushed to locally, only via a merge request using Gitlab.&lt;/p&gt;

&lt;p&gt;So, for me, I'm going to switch to the &lt;code&gt;develop&lt;/code&gt; branch of my code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git checkout -b develop&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We're going to need a CI Token, this is a firebase token that Gitlab can use to act on our behalf. To get one of these, in your terminal, run the command&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;A popup will appear in your browser to login and ask for permissions, once you have done that, back in your terminal, you'll be given a CI Token that looks a bit like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1//03s000000000000000000000F-L9I00000000000000W-_000000Tg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have purposely changed mine for this demo, yours won't have lots of zeros inside it.&lt;/p&gt;

&lt;p&gt;Head over to gitlab as we now need to store this token in the project.&lt;/p&gt;

&lt;p&gt;In your repo in gitlab, click the &lt;em&gt;Settings &amp;gt; CI/CD&lt;/em&gt; and expand the section for &lt;em&gt;Variables&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Click the &lt;code&gt;Add Variable&lt;/code&gt; button and a window like this will appear.&lt;/p&gt;

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

&lt;p&gt;Call the variable &lt;code&gt;FIREBASE_TOKEN&lt;/code&gt;, and paste in the value you got from the &lt;code&gt;ci:login&lt;/code&gt; before. I don't have the variable protected or masked, I have found that sometimes Gitlab has issues when I check these options.&lt;/p&gt;

&lt;p&gt;Save the variable and we're done with this part of the setup.&lt;/p&gt;

&lt;p&gt;Back into our code, create a new file at the &lt;code&gt;ROOT&lt;/code&gt; level of your project called &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;. This is a file that gives Gitlab the instructions needed to build your project.&lt;/p&gt;

&lt;p&gt;Paste in the following into that file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stages:
    - build
    - deploy

image: node:12.13.0-alpine

cache:
    paths:
        - node_modules/

build-staging:
    stage: build
    rules:
        - if: $CI_COMMIT_BRANCH == "staging"
    script:
        # Install dependencies
        - npm install
        # Build App
        - npm run build
    artifacts:
        paths:
            # Build folder
            - dist/firebase-hosting-demo
        expire_in: 1 hour

deploy-staging:
    stage: deploy
    script:
        - npm install -g firebase-tools
        - firebase use --token $FIREBASE_TOKEN staging
        - firebase deploy --only hosting -m "Pipeline $CI_PIPELINE_ID, build $CI_BUILD_ID" --non-interactive --token $FIREBASE_TOKEN
    rules:
        - if: $CI_COMMIT_BRANCH == "staging"

build-production:
    stage: build
    rules:
        - if: $CI_COMMIT_BRANCH == "master"
    script:
        # Install dependencies
        - npm install
        # Build App
        - npm run build
    artifacts:
        paths:
            # Build folder
            - dist/firebase-hosting-demo
        expire_in: 1 hour

deploy-production:
    stage: deploy
    script:
        - npm install -g firebase-tools
        - firebase use --token $FIREBASE_TOKEN production
        - firebase deploy --only hosting -m "Pipeline $CI_PIPELINE_ID, build $CI_BUILD_ID" --non-interactive --token $FIREBASE_TOKEN
    rules:
        - if: $CI_COMMIT_BRANCH == "master"

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

&lt;/div&gt;



&lt;p&gt;I'm not going to go over in depth what this file does, but essentially, it will build and deploy your Angular application for you, but use different Firebase projects depending on what Git branch you use.&lt;/p&gt;

&lt;p&gt;So the idea is, make some code changes on your &lt;code&gt;develop&lt;/code&gt; branch. Once you're happy, commit and push your code to the remote develop branch.&lt;/p&gt;

&lt;p&gt;Do a merge request when you're ready from &lt;code&gt;develop&lt;/code&gt; to &lt;code&gt;staging&lt;/code&gt; and watch as Gitlab will start a pipeline to build your Angular app and deploy it to Firebase.&lt;/p&gt;

&lt;p&gt;When you're happy to go live, do another merge request from &lt;code&gt;staging&lt;/code&gt; to &lt;code&gt;master&lt;/code&gt; in Gitlab and it will build again and deploy to production.&lt;/p&gt;

&lt;p&gt;The first time this runs it might take some time, this is because in my &lt;code&gt;gitlab-ci.yml&lt;/code&gt; file, I have specified to cache the &lt;code&gt;node_modules&lt;/code&gt;, but once this has done, pipelines that run after this should be faster!&lt;/p&gt;

&lt;p&gt;Hope you enjoyed my guide, and any questions, don't hesitate to contact me!.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>gitlab</category>
      <category>firebase</category>
      <category>hosting</category>
    </item>
    <item>
      <title>Angular 8/9/10 + Tailwind CSS Guide</title>
      <dc:creator>Sean Kerwin</dc:creator>
      <pubDate>Tue, 12 Nov 2019 08:56:14 +0000</pubDate>
      <link>https://dev.to/seankerwin/angular-8-tailwind-css-guide-3m45</link>
      <guid>https://dev.to/seankerwin/angular-8-tailwind-css-guide-3m45</guid>
      <description>&lt;p&gt;So, I've found a lot of crappy guides on the internet about how to integrate TailwindCSS with Angular 8, a lot of them involve some nasty hacks that I think are basically, shit. I've collated some information from various sources online to show you how I go about implementing TailwindCSS with Angular 8. If you're reading this and you don't know what TailwindCSS is, two things, one, where the hell have you been the past few years and two, go to tailwindcss.com and feast in the amazingness (is that even a word) that is Tailwind.&lt;/p&gt;

&lt;p&gt;We'll be utilising the @angular-builders/custom-webpack package which will essentially allow us to tailor the webpack build to add tailwind into the build process.&lt;/p&gt;

&lt;p&gt;First things first, install the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i tailwindcss postcss-scss postcss-import postcss-loader @angular-builders/custom-webpack -D&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next you need to open up your Angular project, I'm going to assume you're using sass, as well, why the fuck not?&lt;/p&gt;

&lt;p&gt;Open your &lt;code&gt;styles.scss&lt;/code&gt; file and add the following at the top.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you need to create the tailwind config file, to do so, open your terminal and smash in the following (inside the directory of your app of course).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx tailwind init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we need to extend the webpack config, first, start by creating &lt;code&gt;webpack.config.js&lt;/code&gt; at the root of your project, this is what it should look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
    module: {
        rules: [
            {
                test: /\.scss$/,
                loader: 'postcss-loader',
                options: {
                    ident: 'postcss',
                    syntax: 'postcss-scss',
                    plugins: () =&amp;gt; [
                        require('postcss-import'),
                        require('tailwindcss'),
                        require('autoprefixer'),
                    ]
                }
            }
        ]
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you've added that, modify the &lt;code&gt;angular.json&lt;/code&gt; file to tell it to use the custom builder and config file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "architect": {
    "build": {
      "builder": "@angular-builders/custom-webpack:browser",
      "options": {
        "customWebpackConfig": {
          "path": "./webpack.config.js"
        }
      }
    },
    "serve": {
      "builder": "@angular-builders/custom-webpack:dev-server",
      "options": {
        "customWebpackConfig": {
          "path": "./webpack.config.js"
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we're all up and ready to rumble, add some tailwind classes to an object and run&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Extra&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The whole point of Tailwind is to create custom utilities, you can do so by doing the following:&lt;/p&gt;

&lt;p&gt;Modify your &lt;code&gt;styles.scss&lt;/code&gt; and add 2 new custom imports.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import 'tailwindcss/base';
@import 'tailwindcss/components'; 
@import './custom-tailwind/custom-components.css'; // added
@import 'tailwindcss/utilities';
@import './custom-tailwind/custom-utilities.css'; // added
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure that they're added in the exact order above.&lt;/p&gt;

&lt;p&gt;You can now create a folder inside the src directory called &lt;code&gt;custom-tailwind&lt;/code&gt;&lt;br&gt;
Inside this, you create the 2 files the same names as above, now you can create custom reusable utilities and components, for example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;custom-components.css&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.btn {
  @apply px-4;
  @apply py-2;
  @apply rounded;
  @apply bg-indigo-500;
  @apply text-white;
  transition: 200ms;
}

.btn:hover {
  @apply bg-indigo-600;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now anywhere you want a button, just give it the class &lt;code&gt;.btn&lt;/code&gt; and it will apply all the tailwind classes.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;custom-utilities.css&lt;/code&gt;, you can do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.rotate-0 {
    transform: rotate(0deg);
}
.rotate-90 {
    transform: rotate(90deg);
}
.rotate-180 {
    transform: rotate(180deg);
}
.rotate-270 {
    transform: rotate(270deg);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now anywhere, you can just call these classes. Neat huh!&lt;/p&gt;

&lt;p&gt;Enjoy the power that is TailwindCSS + Angular 8!&lt;/p&gt;

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

&lt;p&gt;I realise this is a repeated post, for some reason I had 3 dev.to accounts (god knows why) and this is the account I wanted to use, so I deleted this post along with the other account and re-created it here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 2:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This also works the same way with Angular 9, I have this working using angular version &lt;code&gt;"@angular/core": "~9.0.0",&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 3: Angular 10.X&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;postcss-loader came with some &lt;em&gt;breaking changes&lt;/em&gt; when it jumped from version 3 to 4.&lt;/p&gt;

&lt;p&gt;I managed to get Angular 10 and Tailwind to play nicely by changing my &lt;code&gt;webpack.config.js&lt;/code&gt; to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        loader: 'postcss-loader',
        options: {
-          ident: 'postcss',
-          syntax: 'postcss-scss',
-          plugins: () =&amp;gt; [
-            require('postcss-import'),
-            require('tailwindcss'),
-            require('autoprefixer'),
-          ],
+          postcssOptions: {
+           ident: 'postcss',
+            syntax: 'postcss-scss',
+            plugins: [
+              require('postcss-import'),
+              require('tailwindcss'),
+              require('autoprefixer'),
            ],
          },
        },
      },
    ],
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to &lt;a href="https://github.com/notiz-dev/notiz/issues/111#issuecomment-689249664"&gt;@phileagleson&lt;/a&gt; for spotting this!&lt;/p&gt;

&lt;p&gt;You can also skip the entire above process and just the the &lt;strong&gt;Schematic&lt;/strong&gt; that was created to do the work for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/garygrossgarten/ngx-tailwind"&gt;garygrossgarten/ngx-tailwind&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note, you will still need to change the &lt;code&gt;webpack.config.js&lt;/code&gt; even if you use the Schematic when using this with &lt;code&gt;postcss-loader&lt;/code&gt; Version 4 and Angular 10&lt;/p&gt;

&lt;h2&gt;
  
  
  Update
&lt;/h2&gt;

&lt;p&gt;Thanks to &lt;a href="https://dev.to/thieugiatri4492"&gt;thieugiatri4492&lt;/a&gt; for pointing out that if you used my manual method of installing Tailwind, and then moved over to use the schematic, you'll need to remove the webpack.config.js before using the schematic otherwise it will throw an error that it already exists!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>tailwindcss</category>
      <category>webpack</category>
      <category>css</category>
    </item>
  </channel>
</rss>
