<?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: Kaushik Mitra</title>
    <description>The latest articles on DEV Community by Kaushik Mitra (@mitrakumar).</description>
    <link>https://dev.to/mitrakumar</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%2F308572%2F5187b4fc-77b6-478c-93dc-2b5970ada150.jpeg</url>
      <title>DEV Community: Kaushik Mitra</title>
      <link>https://dev.to/mitrakumar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mitrakumar"/>
    <language>en</language>
    <item>
      <title>Docker in the Wild: Use Cases &amp; The Survival Commands</title>
      <dc:creator>Kaushik Mitra</dc:creator>
      <pubDate>Thu, 26 Mar 2026 12:47:01 +0000</pubDate>
      <link>https://dev.to/mitrakumar/docker-in-the-wild-use-cases-the-survival-commands-4h8n</link>
      <guid>https://dev.to/mitrakumar/docker-in-the-wild-use-cases-the-survival-commands-4h8n</guid>
      <description>&lt;p&gt;In my last post, we talked about what Docker is and why it’s more than just a buzzword. But knowing the "why" doesn't help when you're staring at a terminal screen wondering how to actually get a container to &lt;em&gt;do&lt;/em&gt; something.&lt;/p&gt;

&lt;p&gt;Now, let's look at where Docker lives in the real world and the specific needed for the day to day work.&lt;/p&gt;




&lt;h3&gt;
  
  
  The "Day-to-Day" Command Handbook 📝
&lt;/h3&gt;

&lt;p&gt;If you’re going to work with Docker, these are the commands you'll find yourself typing over and over again.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;docker build -t &amp;lt;name&amp;gt; .&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Before you can run a container, you need an &lt;strong&gt;Image&lt;/strong&gt;. Think of this as the "factory" step. You’re taking your code and your Dockerfile and baking them into a single package.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pro Tip:&lt;/strong&gt; Don't forget the &lt;code&gt;.&lt;/code&gt; at the end—it tells Docker to look for the Dockerfile in your current folder!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;docker run &amp;lt;image&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the "Let there be light" command. It takes that image you just built, pulls any missing pieces from the cloud, and starts the container.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; &lt;code&gt;docker run nginx&lt;/code&gt; (Starts a web server immediately).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;docker run -d &amp;lt;image&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;-d&lt;/code&gt; stands for &lt;strong&gt;Detached mode&lt;/strong&gt;. Without this, your terminal is "stuck" inside the container process—if you close the window, the app dies. With &lt;code&gt;-d&lt;/code&gt;, the container runs in the background like a silent ninja. 🥷&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;code&gt;docker ps&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Ever wonder, &lt;em&gt;"Wait, is my database actually running?"&lt;/em&gt; &lt;code&gt;docker ps&lt;/code&gt; is your status report. It shows you every container that is currently active, their IDs, and which ports they are using. Use &lt;code&gt;docker ps -a&lt;/code&gt; if you want to see the ones that crashed or stopped, too.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;code&gt;docker exec -it &amp;lt;container_id&amp;gt; bash&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Ever needed to "go inside" the container to check a config file or run a manual database migration? This is how you do it. &lt;code&gt;exec&lt;/code&gt; stands for execute, and &lt;code&gt;-it&lt;/code&gt; makes it interactive so you can actually type things inside.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Think of it as:&lt;/strong&gt; SSHing into your container.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. &lt;code&gt;docker logs &amp;lt;container_id&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Is your app crashing? Did the database fail to start? &lt;code&gt;docker logs&lt;/code&gt; is your first line of defense. It shows you everything the application has printed to the console (STDOUT).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handy flag:&lt;/strong&gt; Use &lt;code&gt;docker logs -f&lt;/code&gt; to "follow" the logs in real-time as they happen. It’s like watching a live heart monitor for your code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. &lt;code&gt;docker stop &amp;lt;container_id&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The polite way to tell a container, "Okay, shift's over. Go home." It gives the processes inside a chance to shut down gracefully.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pro Tip:&lt;/strong&gt; If a container is being stubborn and won't close, you can use &lt;code&gt;docker kill&lt;/code&gt;, but it’s like pulling the power plug—use it sparingly!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. &lt;code&gt;docker rm &amp;lt;container_id&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Just because you stopped a container doesn't mean it's gone. It’s still sitting on your disk like a parked car. &lt;code&gt;docker rm&lt;/code&gt; actually deletes the container instance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shortcut:&lt;/strong&gt; Use &lt;code&gt;docker rm -f $(docker ps -aq)&lt;/code&gt; to delete &lt;strong&gt;every&lt;/strong&gt; container on your machine. (Use with caution!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9. &lt;code&gt;docker rmi &amp;lt;image_id&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If a container is a "running car," the &lt;strong&gt;Image&lt;/strong&gt; is the "blueprints." Over time, you’ll end up with dozens of old versions of images taking up gigabytes of space. &lt;code&gt;rmi&lt;/code&gt; (Remove Image) deletes those blueprints.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. &lt;code&gt;docker system prune&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Nuclear Option. ☢️&lt;/strong&gt;&lt;br&gt;
This is the single most useful command for when your Mac/PC screams "Disk Full." It deletes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All stopped containers.&lt;/li&gt;
&lt;li&gt;All networks not used by at least one container.&lt;/li&gt;
&lt;li&gt;All "dangling" images (the ones that didn't get a proper name).&lt;/li&gt;
&lt;li&gt;All build cache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warning:&lt;/strong&gt; It’s a fresh start. You’ll have to re-download/re-build things next time you need them, but it usually saves me about 20GB of space every month.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;Docker might seem like magic at first, but it’s really just about packaging your environment so you can stop worrying about "it works on my machine" and start focusing on writing code.&lt;/p&gt;

&lt;p&gt;Now that you've mastered the single-container life, things get even more interesting when you have 5 or 10 containers talking to each other.&lt;/p&gt;

&lt;p&gt;After firm grisp on manging single container, we can dive into the world of docker compose for using multiple container &amp;amp; networking between them so how can they talk to each other. &lt;/p&gt;

&lt;p&gt;Please leave a comment below, if you've liked this article or have any kind of queries or suggestions for me.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>cli</category>
      <category>docker</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Deep Dive into Docker: Is it Magic or Just a Fancy Box?</title>
      <dc:creator>Kaushik Mitra</dc:creator>
      <pubDate>Wed, 25 Mar 2026 13:30:51 +0000</pubDate>
      <link>https://dev.to/mitrakumar/deep-dive-into-docker-is-it-magic-or-just-a-fancy-box-112b</link>
      <guid>https://dev.to/mitrakumar/deep-dive-into-docker-is-it-magic-or-just-a-fancy-box-112b</guid>
      <description>&lt;p&gt;Ever heard the phrase, &lt;em&gt;"But it works on my machine!"&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;If you’ve been in tech for more than a week, you probably have. This phrase is the bane of every developer's existence. You spend hours setting up your local environment, only for the production server to throw a tantrum because the PHP version is slightly off or a specific library is missing.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Docker&lt;/strong&gt; enters the chat.&lt;/p&gt;

&lt;h3&gt;
  
  
  What exactly is a Container?
&lt;/h3&gt;

&lt;p&gt;Think of a container as a literal shipping container. &lt;/p&gt;

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

&lt;p&gt;In software, a &lt;strong&gt;Container&lt;/strong&gt; is a lightweight, standalone package that includes everything needed to run an application: code, runtime, system tools, libraries, and settings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do we even need it?
&lt;/h3&gt;

&lt;p&gt;Before Docker, we used &lt;strong&gt;Virtual Machines (VMs) for project deployment and all&lt;/strong&gt;. But VMs are "heavy." They include an entire guest Operating System. If you want to run three apps, you run three OSs. That’s a lot of RAM going to waste.&lt;/p&gt;

&lt;p&gt;Docker is different. It shares the host machine’s OS kernel. It’s fast, starts in seconds, and uses way fewer resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The main wins:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Consistency:&lt;/strong&gt; It works on your laptop, your colleague's Mac, and the AWS EC2 instance exactly the same way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation:&lt;/strong&gt; App A needs Node 14, but App B needs Node 18? No problem. They live in their own little bubbles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability:&lt;/strong&gt; "Build once, run anywhere" isn't just a marketing slogan anymore.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Catch: It’s not all sunshine and rainbows ⛈️
&lt;/h3&gt;

&lt;p&gt;As much as I love Docker, we have to talk about the "Problem" with it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Persistent Data:&lt;/strong&gt; By default, containers are ephemeral. If the container dies, your data dies with it. You have to manage "Volumes" to keep your data safe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Learning Curve:&lt;/strong&gt; Networking between containers can get messy (remember my post on DDEV routing? Yeah, Docker is doing the heavy lifting there).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Since containers share the host kernel, a vulnerability in the kernel could potentially affect all containers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a whole Docker is great for Production Deployment and also for Local Development.&lt;/p&gt;

&lt;p&gt;This was a short details of docker, in the next article I will share some basic commands that is essential for in the day to day usage of docker.&lt;/p&gt;

&lt;p&gt;Please leave a comment below, if you've like this article or have any kind of queries or suggestions for me.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>devops</category>
      <category>docker</category>
      <category>programming</category>
    </item>
    <item>
      <title>Magic behind DDEV &amp; Lando Routing</title>
      <dc:creator>Kaushik Mitra</dc:creator>
      <pubDate>Tue, 28 Oct 2025 11:14:57 +0000</pubDate>
      <link>https://dev.to/mitrakumar/magic-behind-ddev-lando-routing-37m</link>
      <guid>https://dev.to/mitrakumar/magic-behind-ddev-lando-routing-37m</guid>
      <description>&lt;p&gt;Today we'll discuss how the these docker based local environments for development like ddev or lando works.&lt;br&gt;
These tools makes everything magical, and the end user just needs to setup a project run commands like &lt;code&gt;ddev start&lt;/code&gt; or &lt;code&gt;lando start&lt;/code&gt; and all the docker containers will spins up and the user will be able to visit the web page by with the url &lt;em&gt;.ddev.site&lt;/em&gt; or in case of lando &lt;em&gt;.lndo.site&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;😉 Spoiler Alert all these tools uses cheeky DNS mapping &amp;amp; reverse proxy like tool &lt;strong&gt;traefik&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;This guide is perfect for beginners or intermediate developers looking to understand how containerized local dev environments like DDEV use Traefik for networking.&lt;/p&gt;

&lt;p&gt;If you're new to tools like DDEV or Lando and don't know what they are used for, they are local development environment based on Docker. You can easily setup a development environment for Drupal or Wordpress or MERN/MEAN and many other frameworks. As they use Docker containers for installing dependencies local development becomes very easy.&lt;/p&gt;

&lt;p&gt;Let's take an example with DDEV.&lt;br&gt;
In DDEV you can setup a Wordpress Project simply with the following commands, considering DDEV is already setup on your system.&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="nb"&gt;cd&lt;/span&gt; &amp;lt;project-directory-name&amp;gt;
ddev config &lt;span class="nt"&gt;--project-type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;wordpress &lt;span class="nt"&gt;--docroot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
ddev wp core download
ddev wp core &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://&amp;lt;project-directory-name&amp;gt;.ddev.site &lt;span class="nt"&gt;--title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Site Name&amp;gt;"&lt;/span&gt;
&lt;span class="nt"&gt;--admin_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin &lt;span class="nt"&gt;--admin_password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin &lt;span class="nt"&gt;--admin_email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now after setting up the project, &lt;code&gt;ddev start&lt;/code&gt; will spin up all the containers &amp;amp; run your site in the URL &lt;em&gt;https://&amp;lt;project-directory-name&amp;gt;.ddev.site&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Today we'll discuss how this internal routing of https://&amp;lt;project-directory-name&amp;gt;.ddev.site works to your local site.&lt;/p&gt;

&lt;p&gt;This is mainly done in two phases&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DNS Mapping&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;DNS or Domain Name Server mapping is done to assign an IP address to a specific domain. When you type &lt;a href="https://google.com" rel="noopener noreferrer"&gt;https://google.com&lt;/a&gt; on the browser. The browser doesn't know what server to request &amp;amp; how it can serve the html. The domain &lt;a href="https://google.com" rel="noopener noreferrer"&gt;https://google.com&lt;/a&gt; is being resolved to a IP &amp;amp; then the client or the browser requests the server. This is called DNS Mapping.&lt;br&gt;
Now in order the browser to know that accessing a site with the URL https://&amp;lt;project-directory-name&amp;gt;.ddev.site needs to request it's own machine where the project belongs. The URL needs to be resolve to &lt;em&gt;127.0.0.1&lt;/em&gt;.&lt;br&gt;
This custom DNS mapping is created for DDEV &amp;amp; Lando.&lt;br&gt;
You can check this by resolving the URLs *.ddev.site or *.lndo.site&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffq9d5pukckctezwu7amc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffq9d5pukckctezwu7amc.png" alt="DNS Map for *.ddev.site being resolved to 127.0.0.1" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtjj6yvq1ycz5gnxedk3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtjj6yvq1ycz5gnxedk3.png" alt="DNS Map for *.lndo.site being resolved to 127.0.0.1" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this simple way, ddev or lando creates custom URL for local Development.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Proxy Server — Enter Traefik&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that DNS mapping ensures *.ddev.site (or *.lndo.site) resolves to your local machine (127.0.0.1), the next question is: how does your browser’s request for&lt;br&gt;
https://&amp;lt;project-directory-name&amp;gt;.ddev.site actually reach the correct container running your project?&lt;/p&gt;

&lt;p&gt;This is where Traefik steps in.&lt;/p&gt;

&lt;p&gt;Traefik is a modern reverse proxy and load balancer designed for containerized environments. It automatically discovers running containers and routes incoming HTTP/HTTPS requests to the right service — all without you lifting a finger.&lt;/p&gt;

&lt;p&gt;In DDEV (and similarly in Lando), Traefik runs as a global container that listens on ports 80 (HTTP) and 443 (HTTPS). When you run ddev start, your project containers register themselves with Traefik through Docker labels. These labels contain routing information — such as the domain name (.ddev.site) and the internal container port (like 80 or 8080).&lt;/p&gt;

&lt;p&gt;Here’s what happens under the hood when you visit https://&amp;lt;project-directory-name&amp;gt;.ddev.site:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser Request: Your browser sends a request to https://&amp;lt;project-directory-name&amp;gt;.ddev.site.&lt;/li&gt;
&lt;li&gt;DNS Resolution: The *.ddev.site wildcard DNS resolves to 127.0.0.1, pointing to your local machine.&lt;/li&gt;
&lt;li&gt;Traefik Intercepts: The request hits Traefik’s HTTPS listener (port 443). Traefik inspects the hostname .ddev.site and checks its internal routing table.&lt;/li&gt;
&lt;li&gt;Container Discovery: Traefik, using Docker’s API, has already discovered that a container labeled Host(.ddev.site) exists. It knows this container’s internal IP and port.&lt;/li&gt;
&lt;li&gt;Secure Routing: Traefik forwards the request securely to the correct container. It also handles SSL/TLS termination — meaning your site works seamlessly over HTTPS using Traefik’s automatically generated certificates.&lt;/li&gt;
&lt;li&gt;Response: The container serves your app, and Traefik relays the response back to the browser.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So while it looks like you’re visiting a remote, hosted website at https://&amp;lt;project-directory-name&amp;gt;.ddev.site, you’re actually interacting with your own machine. Traefik quietly proxies everything behind the scenes — no hosts file edits, no manual configuration.&lt;/p&gt;

&lt;p&gt;Diving into the details of how these local development environments handled routing was a great learning for me. In a future article we can try and implement similar kind of model with simple docker &amp;amp; docker compose and run our local sites with custom URL.&lt;/p&gt;

&lt;p&gt;Please leave a comment below, if you've like this article or have any kind of queries or suggestions for me.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>docker</category>
      <category>backend</category>
    </item>
    <item>
      <title>Setting up mailcow on mail server on an EC2 instance</title>
      <dc:creator>Kaushik Mitra</dc:creator>
      <pubDate>Sun, 13 Apr 2025 09:55:31 +0000</pubDate>
      <link>https://dev.to/mitrakumar/setting-up-mailcow-on-mail-server-on-an-ec2-instance-2bf6</link>
      <guid>https://dev.to/mitrakumar/setting-up-mailcow-on-mail-server-on-an-ec2-instance-2bf6</guid>
      <description>&lt;p&gt;Recently I've been exploring how we can create our own mail server with our own custom domains.&lt;/p&gt;

&lt;p&gt;In my research I've come across a tool named &lt;code&gt;mailcow&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So let's dive in to learn about &lt;code&gt;mailcow&lt;/code&gt;, and how we can set it up in an AWS EC2 instance.&lt;/p&gt;

&lt;h1&gt;
  
  
  So what is &lt;code&gt;mailcow&lt;/code&gt;?
&lt;/h1&gt;

&lt;p&gt;From the official documentation, it is given that....&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mailcow: dockerized is an open source groupware/email suite based on docker.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;mailcow basically generates a docker-compose file for helping setup a mail server. It already comes with preconfigured components such as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;acme - For creating Let's encrypt Certificates.&lt;/li&gt;
&lt;li&gt;ClamAV - For scanning Anti-virus&lt;/li&gt;
&lt;li&gt;Devcot - For IMAP/POP servers&lt;/li&gt;
&lt;li&gt;MariaDB - For storing user information&lt;/li&gt;
&lt;li&gt;SOGo - Integrated Webmailer&lt;/li&gt;
&lt;li&gt;Memcached - Cache for the webmailer SOGo&lt;/li&gt;
&lt;li&gt;Nginx - Web server for components of the stack&lt;/li&gt;
&lt;li&gt;Olefy - Analysis of Office documents for viruses, macros, etc.&lt;/li&gt;
&lt;li&gt;PHP - Programming language of most web-based mailcow applications&lt;/li&gt;
&lt;li&gt;Postfix - MTA (Mail Transfer Agent) for e-mail traffic on the Internet&lt;/li&gt;
&lt;li&gt;Redis - Storage for spam information, DKIM key, etc.&lt;/li&gt;
&lt;li&gt;Rspamd - Spam filter with automatic learning of spam mails&lt;/li&gt;
&lt;li&gt;Unbound - Integrated DNS server for verifying DNSSEC etc.&lt;/li&gt;
&lt;li&gt;etc. etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  How would we install mailcow then?
&lt;/h1&gt;

&lt;p&gt;Installing &amp;amp; setting up a mailcow server is very easy, you would just need to basically run a docker-compose file for installation. Then everything can be done from the UI.&lt;/p&gt;

&lt;p&gt;But, there are some prerequisites we need to follow....&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up an EC2 instance.
&lt;/h2&gt;

&lt;p&gt;Our mail goal here would be to create an EC2 instance with sufficient RAM &amp;amp; necessary open ports on the server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: For best experience it is recommended to use atleast 4GB RAM, that's why we are using &lt;code&gt;t3.medium&lt;/code&gt; here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the creation of the instance I'm using terraform.&lt;/p&gt;

&lt;p&gt;You can find the full source code from &lt;a href="https://github.com/MitraKumar/mailcow-server-infra" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First of all for our server we need a few necessary ports to be opened.&lt;br&gt;
We can create a security group for this requirement like this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt; &lt;span class="s2"&gt;"mailcow-security-group"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mailcow-sg"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow TLS inbound traffic"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; 
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;465&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;465&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;587&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;587&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;143&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;143&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;993&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;993&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;110&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;110&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;995&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;995&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ingress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4190&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4190&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;egress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;from_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;to_port&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"-1"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mailcow-sg"&lt;/span&gt;
&lt;span class="err"&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;Now, we can create a EC2 instance with the Ubuntu image with the above security group, like this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"mailcow_server"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;ami&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-0e35ddab05955cf57"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t3.medium"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;key_name&lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_key_pair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key_name&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;vpc_security_group_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mailcow-security-group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;user_data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;module}&lt;/span&gt;&lt;span class="s2"&gt;/install-script.sh"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mailcow-vm"&lt;/span&gt;
&lt;span class="err"&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;During the creation of the EC2 instance we are including an install script for installing Docker &amp;amp; Docker compose.&lt;br&gt;
Here is the script....&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Starting Docker Install"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"/home/ubuntu/install-logs"&lt;/span&gt;

&lt;span class="c"&gt;# Add Docker's official GPG key:&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;ca-certificates curl
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 &lt;span class="nt"&gt;-d&lt;/span&gt; /etc/apt/keyrings
&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/docker.asc
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+r /etc/apt/keyrings/docker.asc

&lt;span class="c"&gt;# Add the repository to Apt sources:&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"deb [arch=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; /etc/os-release &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;UBUNTU_CODENAME&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_CODENAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable"&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Completed Docker Install"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"/home/ubuntu/install-logs"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Manage Docker as a non-root user"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"/home/ubuntu/install-logs"&lt;/span&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;
newgrp docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, that we have setup the EC2 instance as needed,  let's move on to our next requirements....&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up an DNS for the mail server
&lt;/h2&gt;

&lt;p&gt;First of all we need a domain for this step, you can buy it from anywhere like namecheap or godady&lt;/p&gt;

&lt;p&gt;I've bought my domain from namecheap, and added my domain to cloudflare for managing various DNS records.&lt;/p&gt;

&lt;p&gt;For the basic mailserver we need atleast two DNS records - MX Record, A Record.&lt;/p&gt;

&lt;h3&gt;
  
  
  MX Record
&lt;/h3&gt;

&lt;p&gt;A MX Record is basically used to point DNS servers where your domain is located.&lt;/p&gt;

&lt;p&gt;Suppose someone trying to send a mail from &lt;a href="mailto:a@gmail.com"&gt;a@gmail.com&lt;/a&gt; to your domain &lt;a href="mailto:user@yoursite.com"&gt;user@yoursite.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, the problem is how gmail would figure out where this &lt;a href="mailto:user@yoursite.com"&gt;user@yoursite.com&lt;/a&gt; is located. So gmail would the DNS server a MX record for yoursite.com.&lt;/p&gt;

&lt;p&gt;We generally add a MX record for your domain to mail.yourdomain.com&lt;/p&gt;

&lt;p&gt;For example, if you have a domain yousite.com&lt;/p&gt;

&lt;p&gt;You would add a MX Record, 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;@ -&amp;gt; mail.yoursite.com 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A Record
&lt;/h3&gt;

&lt;p&gt;An A Record, is used to tell the DNS Servers where your site is.&lt;/p&gt;

&lt;p&gt;Following the given example above, after adding the MX Record, you would need to add the A Record 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;mail.yourdomain.com -&amp;gt; IP Address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we are done with the server configs, let dive in with the actual setup...&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Mailcow
&lt;/h2&gt;

&lt;p&gt;Now that we have setup our server properly, for installing mailcow we need to just basically download the git repo of the mailcow and run the docker image...&lt;/p&gt;

&lt;p&gt;Let's see, how can we do that...&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify current user to have proper privilage
&lt;/h3&gt;

&lt;p&gt;Before cloning the git repo, first we have to check if we have proper user privileges&lt;/p&gt;

&lt;p&gt;Run this command&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="nb"&gt;umask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of the above command should be &lt;code&gt;0022&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For EC2 instance, by default the output should not be as expected. We need to switch the user to root, for this to work.&lt;br&gt;
You can do that by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo su
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Clone mailcow repo
&lt;/h3&gt;

&lt;p&gt;Let's clone to the repo, into &lt;code&gt;/opt&lt;/code&gt; directory and generate the configurations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd /opt
$ git clone git clone https://github.com/mailcow/mailcow-dockerized
$ cd mailcow-dockerized
$ ./generate_config.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: If you wan to change any of the configuration, you can edit the file &lt;code&gt;mailcow.conf&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Run the image
&lt;/h3&gt;

&lt;p&gt;Now that we have setup all the things, let's run the docker compose in the background, and hope everything is working properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the running the image, visit the domain  you have setup with the A record. Like in our example we will open &lt;code&gt;yourdomain.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now that you have installed mailcow, you manage various admin tasks from the UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Few links for managing mailcow
&lt;/h3&gt;

&lt;p&gt;Admin portal can be accessed via &lt;code&gt;/admin&lt;/code&gt;. The default username/password is &lt;code&gt;admin/moohoo&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;All Department portal can be accessed via &lt;code&gt;/department&lt;/code&gt;. The default username/password is &lt;code&gt;department/moohoo&lt;/code&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Using markdown to manage content to NextJS App Router</title>
      <dc:creator>Kaushik Mitra</dc:creator>
      <pubDate>Tue, 26 Mar 2024 02:12:43 +0000</pubDate>
      <link>https://dev.to/mitrakumar/using-markdown-to-manage-content-to-nextjs-app-router-420j</link>
      <guid>https://dev.to/mitrakumar/using-markdown-to-manage-content-to-nextjs-app-router-420j</guid>
      <description>&lt;p&gt;Recently I have been building my portfolio site using NextJs/TailwindCSS.&lt;br&gt;
Here is the link to the site - &lt;a href="https://portfolio-beta-ten-13.vercel.app/" rel="noopener noreferrer"&gt;Visit here&lt;/a&gt;&lt;br&gt;
It's still a work in progress, here is the &lt;a href="https://github.com/MitraKumar/portfolio?tab=readme-ov-file" rel="noopener noreferrer"&gt;source code&lt;/a&gt; for the site.&lt;/p&gt;

&lt;p&gt;In the site I have used markdown files to manage the Projects data on the site.&lt;/p&gt;

&lt;p&gt;Today we will discuss how we can use the markdown files to generate contents for a NextJS site with Server Components and integrate with Typescript.&lt;/p&gt;

&lt;p&gt;So let's dive in...&lt;/p&gt;


&lt;h2&gt;
  
  
  Why &lt;code&gt;next-mdx-remote&lt;/code&gt;...
&lt;/h2&gt;

&lt;p&gt;If we follow the official &lt;a href="https://nextjs.org/docs/pages/building-your-application/configuring/mdx" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; there it is mentioned that how we can basically use &lt;code&gt;.mdx&lt;/code&gt; to generate our JSX components which we can render on our site.&lt;/p&gt;

&lt;p&gt;But following this way can be a bit difficult as it will be very difficult to manage dynamically generated content or if the markdown is coming from somewhere else like some CMS or some other place from the file system.&lt;/p&gt;

&lt;p&gt;To solve this issue we can use a community package &lt;code&gt;next-mdx-remote&lt;/code&gt;. This package actually compiles a given markdown string and generates HTML, so it will solve our problem of maintaining markdown if we want to scale in future and it is coming from some other database or something.&lt;/p&gt;
&lt;h2&gt;
  
  
  Integrating &lt;code&gt;next-mdx-remote&lt;/code&gt; to React Server components in NextJS.
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Installation
&lt;/h3&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;next-mdx-remote
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;

&lt;p&gt;As we are using react server components we can simply fetch the markdown data from a file and display it with the &lt;code&gt;MDXRemote&lt;/code&gt; component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// page.tsx&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;IndexPage&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;markdown_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;markdown_data&lt;/span&gt; &lt;span class="o"&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;notFound&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="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MDXRemote&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;markdown_data&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;/&amp;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;h3&gt;
  
  
  Advance Usage
&lt;/h3&gt;

&lt;p&gt;We can setup our own custom components when generating the HTML form the Markdown files.&lt;/p&gt;

&lt;p&gt;For this we can create our own component which will wrap the libraries &lt;code&gt;MDXRemote&lt;/code&gt; component.&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="c1"&gt;// mdx-remote.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MDXRemote&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MDXRemoteProps&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;next-mdx-remote/rsc&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;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;h1&lt;/span&gt;&lt;span class="p"&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="nx"&gt;ComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&lt;/span&gt;&lt;span class="dl"&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HeaderOne&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="o"&gt;&amp;gt;&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/HeaderOne&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;  &lt;span class="na"&gt;h2&lt;/span&gt;&lt;span class="p"&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="nx"&gt;ComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h2&lt;/span&gt;&lt;span class="dl"&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HeaderTwo&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="o"&gt;&amp;gt;&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/HeaderTwo&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;  &lt;span class="na"&gt;p&lt;/span&gt;&lt;span class="p"&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="nx"&gt;ComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p&lt;/span&gt;&lt;span class="dl"&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Paragragraph&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="o"&gt;&amp;gt;&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Paragragraph&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;  &lt;span class="na"&gt;img&lt;/span&gt;&lt;span class="p"&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="nx"&gt;ComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;img&lt;/span&gt;&lt;span class="dl"&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MdxImage&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="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;  &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&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="nx"&gt;ComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MdxLink&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="o"&gt;&amp;gt;&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/MdxLink&amp;gt;&lt;/span&gt;&lt;span class="err"&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;function&lt;/span&gt; &lt;span class="nf"&gt;CustomMDX&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="nx"&gt;MDXRemoteProps&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MDXRemote&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="nx"&gt;components&lt;/span&gt;&lt;span class="o"&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;components&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;components&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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 these HeaderOne, HeaderTwo, etc can be simple components with our custom styles.&lt;/p&gt;

&lt;p&gt;For example...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// HeaderOne.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ComponentProps&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;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HeaderOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;ComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&lt;/span&gt;&lt;span class="dl"&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;{&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;h1&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;"mb-6 mt-16 text-5xl"&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;children&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;h1&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// MDXImage.tsx&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="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ComponentProps&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;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MdxImageProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;img&lt;/span&gt;&lt;span class="dl"&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;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MdxImage&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="nx"&gt;MdxImageProps&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="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;"flex justify-center"&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;"border-4 border-primary"&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="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&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;props&lt;/span&gt;&lt;span class="p"&gt;.&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="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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;300&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have created our custom wrapper component for the &lt;code&gt;MDXRemote&lt;/code&gt; we can use this in our server component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /projects/[title]/page.tsx&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;IndexPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;params&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="kr"&gt;string&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;markdown_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProjectWithTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;markdown_data&lt;/span&gt; &lt;span class="o"&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;notFound&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="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MDXRemote&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;markdown_data&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;/&amp;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;Now as we are using NextJS we can further more optise our site by staticly generating the page with &lt;code&gt;generateStaticParams&lt;/code&gt; function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /projects/[title]/page.tsx&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateStaticParams&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="nf"&gt;getProjectTitles&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 source code for the above can be found &lt;a href="https://github.com/MitraKumar/portfolio" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So, in conclusion we discussed how we can integrate this community package &lt;code&gt;next-mdx-remote&lt;/code&gt; for managing content with markdown and also how we can use Typescript to add proper types and have proper type safe development.&lt;/p&gt;

&lt;p&gt;If you have any discussions regarding the topic feel free to comment below.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>typescript</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Use bunx for running npm packages with lightning fast speed.</title>
      <dc:creator>Kaushik Mitra</dc:creator>
      <pubDate>Mon, 11 Sep 2023 20:34:38 +0000</pubDate>
      <link>https://dev.to/mitrakumar/use-bunx-for-running-npm-packages-with-lightning-fast-speed-2p32</link>
      <guid>https://dev.to/mitrakumar/use-bunx-for-running-npm-packages-with-lightning-fast-speed-2p32</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Use Case for the package&lt;/li&gt;
&lt;li&gt;Comparing with npx&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;bun&lt;/code&gt; is the latest and greatest runtime for Javascript  which ships with many features like built in Typescript support and testing support and etc. etc.. bunx, alias for &lt;code&gt;bun x&lt;/code&gt;, is a package manger for bun which can be used for auto installing and running npm packages. We can you &lt;code&gt;bunx&lt;/code&gt; just similarly like we use &lt;code&gt;npx&lt;/code&gt; or &lt;code&gt;yarn dlx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://twitter.com/jarredsumner/status/1606163655527059458" rel="noopener noreferrer"&gt;this&lt;/a&gt; twitter post, bunx is 100x faster than npx, which means we can use bunx and run our npm cli with lightning fast speed.&lt;/p&gt;

&lt;p&gt;Today we will discuss an use case of running a npm package with bunx and compare the result with running it with npx.&lt;/p&gt;

&lt;p&gt;You can view the package from &lt;a href="https://www.npmjs.com/package/phil-s-osophy" rel="noopener noreferrer"&gt;here&lt;/a&gt;, it is a simple package that I wrote which generates a random quote of Phil Dunphy from Mordern Family. You can also view a &lt;a href="https://dev.to/mitrakumar/journey-of-creating-and-publishing-a-nodejs-package-with-typescript-eslint-support-3gh7"&gt;post&lt;/a&gt; that I have written with my learnings and take aways from creating this package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use case for the package
&lt;/h2&gt;

&lt;p&gt;As the package &lt;code&gt;phil-s-osophy&lt;/code&gt; just spits out basic string output we can pipe that to any program, like I have used to pipe the value in &lt;code&gt;cowsay&lt;/code&gt; and added the whole thing at the bottom of my zshrc file to show text at every shell creation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bunx phil-s-osophy | bunx cowsay
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Comparing with npx
&lt;/h2&gt;

&lt;p&gt;To compare my changes with the npx, I have created a function which will run the shell few times and time it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;timezsh&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;seq &lt;/span&gt;1 10&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; /usr/bin/time &lt;span class="nv"&gt;$SHELL&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So after running both my program with bunx and npx I timed it to aroud &lt;code&gt;0.3 to 0.4s&lt;/code&gt; when running with bunx but when running with npx the program took around &lt;code&gt;2s&lt;/code&gt; to ran.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: there are many more things happening in my zshrc file, but I am ignoring this as they are running in bot scenarios.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Left running - &lt;code&gt;bunx phil-s-osophy | bunx cowsay&lt;/code&gt;&lt;br&gt;
Right running - &lt;code&gt;npx phil-s-osophy | npx cowsay&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg6ixcxkihkrdy0rjjvl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg6ixcxkihkrdy0rjjvl.jpeg" alt="comapare bunx v npx - screengrab" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So, in conclusion we have seen how bunx is so much faster than npx and how we can use this lightning fast speed to install and use packages for that great developer experience.&lt;/p&gt;

&lt;p&gt;For more information about the bun, you can visit &lt;a href="https://bun.sh/docs" rel="noopener noreferrer"&gt;bun.sh&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>npm</category>
      <category>bunjs</category>
    </item>
    <item>
      <title>Journey of creating and publishing a nodejs package with typescript &amp; eslint support</title>
      <dc:creator>Kaushik Mitra</dc:creator>
      <pubDate>Fri, 08 Sep 2023 22:26:38 +0000</pubDate>
      <link>https://dev.to/mitrakumar/journey-of-creating-and-publishing-a-nodejs-package-with-typescript-eslint-support-3gh7</link>
      <guid>https://dev.to/mitrakumar/journey-of-creating-and-publishing-a-nodejs-package-with-typescript-eslint-support-3gh7</guid>
      <description>&lt;p&gt;Today we will discuss how I've written a npm package and published it to &lt;a href="https://www.npmjs.com/package/phil-s-osophy" rel="noopener noreferrer"&gt;npmjs&lt;/a&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can checkout the codebase from &lt;a href="https://github.com/MitraKumar/phil-s-osophy" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a simple package which just generates random quotes from Phil Dunphy, the lovable and hilarious character from the TV show Modern Family.  I have chosen Phil Dunphy as I love Mordern Family and he is one of my favorite caracter from the show.&lt;/p&gt;

&lt;p&gt;The target of this package was not to create something unique and useful for everyone (though if you are a fan of Phill Dunphy you may love this idea 😉), but it was to learn how we can use these technologies to build packages in a simple and efficient manner.&lt;/p&gt;

&lt;h4&gt;
  
  
  Technology Used
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Typescript for writing the business logic and have used &lt;a href="https://tsup.egoist.dev/" rel="noopener noreferrer"&gt;tsup&lt;/a&gt; for compiling to javascript files. &lt;/li&gt;
&lt;li&gt;ESlint for linting the typescript code&lt;/li&gt;
&lt;li&gt;Also have used Github Actions for linting the code whenever a new pull request is being created.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Setting up local environment for creating packages
&lt;/h4&gt;

&lt;p&gt;For setting up a local environment, we can start like a basic node js project.&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="nb"&gt;mkdir &lt;/span&gt;my_project
&lt;span class="nb"&gt;cd &lt;/span&gt;my_prject
npm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that we need to add the main entry point of our package as well as a bin file.&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phil-s-osophy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Phil Dunphy's amazing life lessons from Mordern Family."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.mjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.d.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bin"&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;"phil-o-osophy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist/index.js"&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;"repository"&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;"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;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"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;"git+https://github.com/MitraKumar/phil-s-osophy.git"&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;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MitraKumar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bugs"&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;"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://github.com/MitraKumar/phil-s-osophy/issues"&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;"homepage"&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://github.com/MitraKumar/phil-s-osophy#readme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&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;In my scenario since it I am compiling the javascript with tsup I've added the files in here.&lt;/p&gt;

&lt;p&gt;And in the typescript file we need to add shebang in front of the file&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="cp"&gt;#! /usr/bin/env node
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After updating all this we can simply run &lt;code&gt;npm install -g .&lt;/code&gt; from the project directory to use the package.&lt;/p&gt;

&lt;h4&gt;
  
  
  Project Setup with Typescript
&lt;/h4&gt;

&lt;p&gt;The main business logic for the package is written in typescript and the logic is very simple, it's just accessing a random element from a list of quotes and printing it out. Again the project was not to create anything unique, it is just fun enough for me to learn these things.&lt;/p&gt;

&lt;p&gt;For compiling typescript file I have used tsup as a dev dependency, which is very useful and intuitive for compiling to javascript files. To make this process seamless I've added a npm script to build the project.&lt;/p&gt;

&lt;p&gt;For the configuration of tsup we need to create a &lt;code&gt;tsup.config.ts&lt;/code&gt; file.&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;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tsup&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;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;es2020&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;format&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;cjs&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;esm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;splitting&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="na"&gt;sourcemap&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;clean&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;dts&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then after adding this I added the build command in npm scripts and voila it all worked seamlessly.&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phil-s-osophy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsup ./src"&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="err"&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;This is really helpful as we get the power of types and the seamless process of compiling to javascript files.&lt;/p&gt;

&lt;h4&gt;
  
  
  Linting with ESLint
&lt;/h4&gt;

&lt;p&gt;Linting is must in a project, this is a small simple enough project but for a live project with many contributors linting is must otherwise without following a proper coding standard it will be difficult over time to maintain a project.&lt;/p&gt;

&lt;p&gt;I have used ESlint for checking the linting of the project. Setting up ESLint is simple enough but we have to add few dependencies to help us out here...&lt;/p&gt;

&lt;p&gt;in the package.json we need to add few of the dev dependencies such as&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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&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;"@typescript-eslint/eslint-plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^6.6.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript-eslint/parser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^6.6.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"eslint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.48.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can install this dependencies by running&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;-D&lt;/span&gt; eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that we need to add a &lt;code&gt;.eslintrc&lt;/code&gt; file, with some basic rulesets.&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;"root"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@typescript-eslint/parser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&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="s2"&gt;"@typescript-eslint"&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;"extends"&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="s2"&gt;"eslint:recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@typescript-eslint/eslint-recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@typescript-eslint/recommended"&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;"rules"&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;"@typescript-eslint/no-explicit-any"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"indent"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"linebreak-style"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unix"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"quotes"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"double"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"semi"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And all the configurations are done, now we can simply add a npm script &lt;code&gt;eslint ./src --ext .ts&lt;/code&gt; to lint our files.&lt;/p&gt;

&lt;p&gt;But this will cause an issue as ESLint will not trigger any typescript error, for that we can simply check it with &lt;code&gt;tsc --noEmit ./src/index.ts&lt;/code&gt;. So for linting we can simply add a script like this &lt;code&gt;tsc --noEmit ./src/index.ts; eslint ./src --ext .ts&lt;/code&gt; to run both of them sequentially.&lt;/p&gt;

&lt;p&gt;Also we can add a script to fix the linting errors with ESlint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  ...
  "scripts": {
    "lint": "tsc --noEmit ./src/index.ts; eslint ./src --ext .ts",
    "fix": "eslint ./src --ext .ts --fix",
    ...
  },
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voila, linting is also setup in our project.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up Github Actions for checking coding standards
&lt;/h4&gt;

&lt;p&gt;In a real world we probably cannot expect everyone to properly lint code and the Pushing it. So we need to setup a Github Action to generate a check for linting errors if any whenever a PR is being generated.&lt;/p&gt;

&lt;p&gt;Setting up such action is pretty easy, we just need create a yml file in the directory &lt;code&gt;.github/workflows&lt;/code&gt; like I've created a file &lt;code&gt;.github/workflows/linter.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Code Checker&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;linting&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checking coding standards &amp;amp; type checking.&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup node environment&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;latest'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm clean-install&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run linting &amp;amp; type checking&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run lint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow file is mainly divided into three sections&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name - Name of the workflow&lt;/li&gt;
&lt;li&gt;Event - On which event the workflow will trigger, like in this scenario it will trigger on creating a Pull request against the branch &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Jobs - What jobs will run in this workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jobs also have several aspects to understand, the main thing being &lt;code&gt;steps&lt;/code&gt;&lt;br&gt;
Steps basically mentions what the a job will do in a sequential order, like here it is mentioned that the job will first checkout the repo, then setup node environment then install all dependencies and then run our lint script from above.&lt;/p&gt;

&lt;p&gt;And that's it, now creating a PR will automatically run this jobs and will show a green check mark ✅&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvm6hp0k9syylsgq4t548.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvm6hp0k9syylsgq4t548.png" alt="Github Screenshot for Workflow Action Checks" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;So in conclusion I will say, this was a fun simple enough project which helped me learn a lot of things. And if any of you have any idea of improving the project, even if it's a change in README file, you are more than welcome to submit a Pull Request and I will be happy to merge it.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>beginners</category>
      <category>devops</category>
      <category>node</category>
    </item>
    <item>
      <title>mordern_navbar</title>
      <dc:creator>Kaushik Mitra</dc:creator>
      <pubDate>Sun, 05 Jan 2020 00:01:24 +0000</pubDate>
      <link>https://dev.to/mitrakumar/mordernnavbar-2oj5</link>
      <guid>https://dev.to/mitrakumar/mordernnavbar-2oj5</guid>
      <description>&lt;p&gt;my first post in this community, hope to get some love.&lt;/p&gt;

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

</description>
      <category>codepen</category>
    </item>
  </channel>
</rss>
